<?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"><channel><title><![CDATA[MaxySpark's ZombieLand]]></title><description><![CDATA[MaxySpark's ZombieLand]]></description><link>https://blog.maxyspark.me</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Apr 2026 09:52:27 GMT</lastBuildDate><atom:link href="https://blog.maxyspark.me/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Using wkhtmltopdf on Amazon Linux 2023 (ARM64) in EC2: A Lightweight Alternative to Puppeteer for HTML to PDF Conversion]]></title><description><![CDATA[Background
We had a requirement to include a Terms and Conditions block in an existing PDF. The terms and conditions were represented as rows of an HTML table. For this, we were converting HTML to PDF using the puppeteer-html-pdf Node.js package.
On ...]]></description><link>https://blog.maxyspark.me/using-wkhtmltopdf-on-amazon-linux-2023-arm64-in-ec2-a-lightweight-alternative-to-puppeteer-for-html-to-pdf-conversion</link><guid isPermaLink="true">https://blog.maxyspark.me/using-wkhtmltopdf-on-amazon-linux-2023-arm64-in-ec2-a-lightweight-alternative-to-puppeteer-for-html-to-pdf-conversion</guid><category><![CDATA[puppeteer]]></category><category><![CDATA[pdf]]></category><category><![CDATA[wkhtmltopdf]]></category><category><![CDATA[amazon-linux-2023]]></category><category><![CDATA[arm64]]></category><category><![CDATA[aarch64]]></category><dc:creator><![CDATA[Bhargab Hazarika]]></dc:creator><pubDate>Mon, 18 Nov 2024 18:50:33 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1731956228523/81ac345e-7b11-46c8-869c-426c80a09c61.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-background">Background</h3>
<p>We had a requirement to include a <strong>Terms and Conditions</strong> block in an existing PDF. The terms and conditions were represented as rows of an HTML table. For this, we were converting HTML to PDF using the <a target="_blank" href="https://www.npmjs.com/package/puppeteer-html-pdf"><code>puppeteer-html-pdf</code></a> Node.js package.</p>
<p>On our development server (running on an EC2 instance with Ubuntu and an x86_64 CPU architecture), this approach worked perfectly. Here’s the code snippet we used:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> PuppeteerHTMLPDF = <span class="hljs-built_in">require</span>(<span class="hljs-string">"puppeteer-html-pdf"</span>);
<span class="hljs-keyword">const</span> options = { <span class="hljs-attr">format</span>: <span class="hljs-string">"A4"</span> };
<span class="hljs-keyword">const</span> file = {
  <span class="hljs-attr">content</span>: <span class="hljs-string">`&lt;div style="padding: 20px"&gt;&lt;h2 style="text-align: center;"&gt;Terms And Conditions&lt;/h2&gt;<span class="hljs-subst">${customTnc}</span>&lt;/div&gt;`</span>,
};

<span class="hljs-keyword">const</span> htmlPDF = <span class="hljs-keyword">new</span> PuppeteerHTMLPDF();
htmlPDF.setOptions(options);
<span class="hljs-keyword">const</span> customTncBuffer = <span class="hljs-keyword">await</span> htmlPDF.create(file.content);
</code></pre>
<h3 id="heading-the-problem">The Problem</h3>
<p>When we tried the same solution on our staging server, it failed. Our staging server was managed by a third-party firm and ran on <strong>Amazon Linux 2023</strong> with an <strong>ARM64 (aarch64)</strong> architecture.</p>
<p>The issue arose because Puppeteer depends on a Chromium binary, <a target="_blank" href="https://github.com/puppeteer/puppeteer/issues/7740">which is not natively supported on ARM64</a>. Despite trying solutions suggested in blogs and tools like ChatGPT, we couldn’t resolve the problem.</p>
<h3 id="heading-limitations-of-other-alternatives">Limitations of Other Alternatives</h3>
<p>We explored several other Node.js packages, such as <code>jsPDF</code>, <code>Playwright</code>, and <code>html-pdf</code>. Unfortunately, none of these either met our requirements or worked on the staging server.</p>
<h3 id="heading-the-solution-wkhtmltopdf">The Solution: wkhtmltopdf</h3>
<p>Finally, we discovered the command-line tool <code>wkhtmltopdf</code>. After some troubleshooting, we managed to install it on Amazon Linux 2023 (ARM64). Here's how you can do it easily:</p>
<h3 id="heading-installing-wkhtmltopdf-on-amazon-linux-2023-arm64">Installing wkhtmltopdf on Amazon Linux 2023 (ARM64)</h3>
<p>Run the following commands:</p>
<pre><code class="lang-bash">sudo yum install --assumeyes zlib fontconfig freetype libX11 libXext libXrender xorg-x11-fonts-75dpi xorg-x11-fonts-Type1
sudo yum localinstall -y https://repo.almalinux.org/almalinux/8/AppStream/aarch64/os/Packages/libpng15-1.5.30-7.el8.aarch64.rpm
sudo yum localinstall -y https://yum.oracle.com/repo/OracleLinux/OL8/appstream/aarch64/getPackage/compat-openssl10-1.0.2o-3.el8.aarch64.rpm
sudo yum localinstall -y https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6-1/wkhtmltox-0.12.6-1.amazonlinux2.aarch64.rpm
</code></pre>
<h3 id="heading-implementing-wkhtmltopdf-in-nodejs">Implementing wkhtmltopdf in Node.js</h3>
<p>After installing <code>wkhtmltopdf</code>, we switched to the corresponding Node.js package. This approach worked perfectly. Here’s the updated implementation:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> wkhtmltopdf = <span class="hljs-built_in">require</span>(<span class="hljs-string">"wkhtmltopdf"</span>);
<span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">"fs"</span>);
<span class="hljs-keyword">const</span> os = <span class="hljs-built_in">require</span>(<span class="hljs-string">"os"</span>);
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">"path"</span>);

<span class="hljs-keyword">const</span> tncHtmlContent = <span class="hljs-string">`&lt;div style="padding: 20px"&gt;&lt;h2 style="text-align: center;"&gt;Terms And Conditions&lt;/h2&gt;<span class="hljs-subst">${customTnc}</span>&lt;/div&gt;`</span>;

<span class="hljs-comment">// Define a temporary file path</span>
<span class="hljs-keyword">const</span> tempFilePath = path.join(os.tmpdir(), <span class="hljs-string">`tempTnc_<span class="hljs-subst">${<span class="hljs-built_in">Date</span>.now()}</span>.pdf`</span>);

<span class="hljs-comment">// Generate PDF for Terms and Conditions</span>
<span class="hljs-keyword">await</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
  wkhtmltopdf(tncHtmlContent, { <span class="hljs-attr">output</span>: tempFilePath }, <span class="hljs-function">(<span class="hljs-params">err</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (err) {
      reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Error generating T&amp;C PDF: <span class="hljs-subst">${err.message}</span>`</span>));
    } <span class="hljs-keyword">else</span> {
      resolve();
    }
  });
});

<span class="hljs-comment">// Read the generated PDF</span>
<span class="hljs-keyword">const</span> customTncBuffer = fs.readFileSync(tempFilePath);

<span class="hljs-comment">// Clean up temporary file</span>
fs.unlinkSync(tempFilePath);
</code></pre>
<h3 id="heading-key-takeaways">Key Takeaways</h3>
<ol>
<li><p><strong>Puppeteer Limitations</strong>: Puppeteer relies on Chromium, which isn’t supported on ARM64 in Amazon Linux 2023.</p>
</li>
<li><p><strong>Advantages of wkhtmltopdf</strong>: It is a lightweight command-line tool that doesn’t require Chromium and works seamlessly with ARM64.</p>
</li>
<li><p><strong>Installation Challenges</strong>: Installing <code>wkhtmltopdf</code> on Amazon Linux 2023 with ARM64 requires additional dependencies, but the commands above simplify the process.</p>
</li>
</ol>
<p>This solution allowed us to seamlessly generate PDFs with the desired Terms and Conditions block, even on our ARM64 staging server.</p>
]]></content:encoded></item></channel></rss>