<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:blogger='http://schemas.google.com/blogger/2008' xmlns:georss='http://www.georss.org/georss' xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7442072150765022610</id><updated>2026-10-19T11:28:00.229+05:30</updated><category term="PHP"/><category term="JavaScript"/><category term="Android"/><category term="PHP Framework"/><category term="Sencha Touch"/><category term="Laravel"/><category term="iOS"/><category term="Android App"/><category term="Magento"/><category term="Sencha Touch 2"/><category term="Mobile Application"/><category term="Web Development"/><category term="Cordova"/><category term="Sencha"/><category term="Laravel 5.2"/><category term="ExtJs"/><category term="Web Application"/><category term="Apple"/><category term="Objective C"/><category term="iOS App"/><category term="Mobile"/><category term="Xcode"/><category term="Cross Platform Application Development"/><category term="Laravel 5.4"/><category term="iPhone"/><category term="HTML5"/><category term="Hybrid Application Development"/><category term="Magento API"/><category term="Magento Admin"/><category term="Phonegap"/><category term="CSS3"/><category term="Java"/><category term="eCommerce"/><category term="API"/><category term="Amazon"/><category term="Android Application"/><category term="Android SDK"/><category term="Magento Mobile"/><category term="PHP Extensions"/><category term="React"/><category term="ReactJs"/><category term="Cloud Computing"/><category term="iOS 10"/><category term="Amazon EC2"/><category term="AngularJs"/><category term="ArtificialIntelligence"/><category term="Developers"/><category term="MVC"/><category term="NodeJs"/><category term="Programmers"/><category term="iOS 7"/><category term="iPad"/><category term="jQuery"/><category term="AI"/><category term="Amazon AWS"/><category term="Business Applications"/><category term="CSS"/><category term="Docker"/><category term="Google"/><category term="Information Technology"/><category term="MySql"/><category term="OSX"/><category term="devops"/><category term="kubernetes"/><category term="Google API"/><category term="Linux"/><category term="List"/><category term="Location Services"/><category term="Online Order"/><category term="Push Notification"/><category term="React Native"/><category term="Technology"/><category term="Web Service"/><category term="Channel Advisor PHP API"/><category term="Cybersecurity"/><category term="Database"/><category term="Framework"/><category term="GPS"/><category term="IT Professionals"/><category term="MAC"/><category term="Machine Learning"/><category term="Magento 2"/><category term="Mobile Cart"/><category term="Mobile Website."/><category term="Productivity Applications. Mobile Application"/><category term="Programming"/><category term="Server Admin"/><category term="TypeScript"/><category term="UI/UX"/><category term="Accordion"/><category term="Angular"/><category term="Apache"/><category term="Attendance Management"/><category term="Beginners"/><category term="Cloud Native"/><category term="Cocoa Application"/><category term="Command Line"/><category term="Composer"/><category term="Data Analysis"/><category term="ExtJs Grid"/><category term="ExtJs editor grid"/><category term="Good Programmer"/><category term="Google Search"/><category term="HTTPS"/><category term="Location aware apps"/><category term="MAMP"/><category term="Magento Mobile Site"/><category term="Mobile Commerce"/><category term="Mobile Website"/><category term="Order"/><category term="SSL"/><category term="Socket"/><category term="Software Engineering"/><category term="Swift"/><category term="System Admin"/><category term="Terminal"/><category term="Troubleshooting"/><category term="Ubuntu"/><category term=".Net"/><category term="Animation"/><category term="Application Security"/><category term="Background Services"/><category term="Big Data"/><category term="Bootstrap"/><category term="Business"/><category term="Camera"/><category term="Configurable Products"/><category term="Data Scraping"/><category term="DataView"/><category term="DevSecOps"/><category term="Device Driver"/><category term="Dynamic Loading"/><category term="Eclipse"/><category term="Employee Tracking"/><category term="Ext.Direct"/><category term="ExtJs 4.0.2a"/><category term="ExtJs 4.1"/><category term="Facebook"/><category term="FireBase"/><category term="GCM"/><category term="Getting Started"/><category term="Great Programmers"/><category term="IOT"/><category term="IT"/><category term="Image"/><category term="Indexing"/><category term="Internet of Things"/><category term="JSON"/><category term="Magento Commands"/><category term="Magento Mobile Store"/><category term="Magento Mobile Theme"/><category term="Magento Synchronization"/><category term="Maps API"/><category term="MediaRecorder"/><category term="Models"/><category term="NLP"/><category term="Natural Language Processing"/><category term="Nginx"/><category term="OOP"/><category term="Page Size"/><category term="Paging"/><category term="Paperless"/><category term="PhpMyAdmin"/><category term="Product Page"/><category term="Production Debugging"/><category term="Programmatically"/><category term="Python"/><category term="SOAP"/><category term="SQL"/><category term="SSH"/><category term="SSL Certificate"/><category term="Service"/><category term="TinyMCE"/><category term="Tips"/><category term="Touch Events"/><category term="Tracking"/><category term="Windows Azure"/><category term="XML"/><category term="cURL"/><category term="container"/><category term="kubectl"/><category term="mCommerce"/><category term=".Net Framework"/><category term=".Net Versioning"/><category term="API Keys"/><category term="API Security"/><category term="Abstraction"/><category term="Ad Hoc"/><category term="Agile"/><category term="Ajax"/><category term="Amazon RDS"/><category term="Amazon S3"/><category term="Amazon SES"/><category term="Angular 7"/><category term="Angular 9"/><category term="Artisan"/><category term="Asp.Net Web Service"/><category term="Assembly"/><category term="Associations"/><category term="Audio"/><category term="Automation"/><category term="Axes"/><category term="Big Commerce"/><category term="Brochures"/><category term="Browser Resize"/><category term="Button"/><category term="CA"/><category term="CI/CD"/><category term="CRUD"/><category term="Carousel"/><category term="Category Import"/><category term="Certbot"/><category term="Certificate Chain"/><category term="Chatbots"/><category term="Cloud"/><category term="Code Security"/><category term="Coding"/><category term="Compile"/><category term="Computer"/><category term="Computer Engineers"/><category term="Constraint"/><category term="Container Security"/><category term="Containers"/><category term="Copy Paste"/><category term="CrashLoopBackOff"/><category term="Customer Engagement"/><category term="DLL Hell"/><category term="Data Encapsulation"/><category term="Data Hiding"/><category term="Data Mining"/><category term="Database Administrator"/><category term="Decision Making"/><category term="Deep Learning"/><category term="Design Patter"/><category term="DevOps Tutorial"/><category term="Digital Marketing"/><category term="Digitization"/><category term="Directions API"/><category term="Directive"/><category term="Docs"/><category term="Driver"/><category term="E-Commerce"/><category term="EI"/><category term="Eating Habits"/><category term="Eco Friendly"/><category term="Error 150"/><category term="Exit Code 137"/><category term="Expense Management System"/><category term="Express"/><category term="Ext Designer"/><category term="ExtJs Grid Panel HTML controls"/><category term="ExtJs MVC"/><category term="ExtJs Panel"/><category term="ExtJs data store"/><category term="FMCG"/><category term="FTP"/><category term="Fiction"/><category term="Field Services"/><category term="Foods"/><category term="Force.com"/><category term="Foreign Key Primary Key"/><category term="Form Panel"/><category term="Format"/><category term="FrameLayout"/><category term="Funny"/><category term="GAC"/><category term="GIF"/><category term="GetStream"/><category term="GetStream.io"/><category term="Getting Started."/><category term="Git Security"/><category term="Google Play Services"/><category term="Google Play."/><category term="Google Rank"/><category term="Grafana"/><category term="Grid"/><category term="Grid Layout"/><category term="HR Industry"/><category term="HR Software"/><category term="HTTP"/><category term="Height"/><category term="Helm"/><category term="Hiring"/><category term="Home"/><category term="Image Gallery"/><category term="Image Sequences."/><category term="In-app"/><category term="India"/><category term="Inheritance"/><category term="Innovation"/><category term="Installation"/><category term="Instant"/><category term="Intermediate Certificate"/><category term="Inventory"/><category term="JAR"/><category term="JSTree"/><category term="Joining"/><category term="Joomla"/><category term="Knockout JS"/><category term="Kubernetes Debugging"/><category term="Kubernetes Logging"/><category term="Kubernetes Resources"/><category term="Kubernetes Troubleshooting"/><category term="Language"/><category term="Leaders"/><category term="Let&#39;s Encrypt"/><category term="Location aware apps."/><category term="Loki"/><category term="Lumen"/><category term="MEAN"/><category term="MERN"/><category term="MS SQL"/><category term="MVVM"/><category term="Magento Salesforce"/><category term="Marketing"/><category term="Memory Management"/><category term="Menu"/><category term="Messaging"/><category term="Mobile App"/><category term="MongoDB"/><category term="Mouse Events"/><category term="Native Application"/><category term="Navigation"/><category term="Non Fiction"/><category term="OOMKilled"/><category term="OOPS"/><category term="Object Oriented Programming"/><category term="Observability"/><category term="Offline Support"/><category term="Open Source Security"/><category term="OpenSSL"/><category term="Operating System"/><category term="PDF"/><category term="Panel"/><category term="Payment"/><category term="Paypal"/><category term="Payroll"/><category term="Pear"/><category term="Peer"/><category term="Photoshop"/><category term="Pioneers"/><category term="Pivot Table"/><category term="Plist"/><category term="Plugin"/><category term="Polymorphism"/><category term="PrestaShop"/><category term="Project Manager"/><category term="Promtail"/><category term="Proxies"/><category term="Query String"/><category term="R&amp;D"/><category term="REST API"/><category term="Ratchet"/><category term="Recording"/><category term="Redis"/><category term="Refactoring"/><category term="Refresh row"/><category term="Remote Staff"/><category term="Research"/><category term="Restaurant"/><category term="Routes"/><category term="RowDetails"/><category term="SEO"/><category term="SFTP"/><category term="Salesforce"/><category term="Scripts"/><category term="Scrollbar"/><category term="Secrets Management"/><category term="Secure Coding"/><category term="Security"/><category term="Serverless"/><category term="Shopping cart"/><category term="Silverlight"/><category term="SlideMenu"/><category term="Smart Devices"/><category term="Socket.io"/><category term="Softwares"/><category term="Sound Quality"/><category term="Splash Screen"/><category term="Sqlite"/><category term="Steve Jobs"/><category term="Stores"/><category term="Story Telling"/><category term="Strong Name"/><category term="Submit"/><category term="Success Story"/><category term="Supply Chain Management"/><category term="Table Pivoting"/><category term="TapHold"/><category term="Task. Alarm."/><category term="Template"/><category term="TensorFlow"/><category term="Testing"/><category term="TomatoCart"/><category term="Touch Charts"/><category term="Translation"/><category term="Tree"/><category term="Trivy"/><category term="UnitTest"/><category term="Update"/><category term="Vehicle Tracking"/><category term="Video"/><category term="Vim"/><category term="VirtueMart"/><category term="Vulnerability Management"/><category term="Vulnerability Scanning"/><category term="Wearables"/><category term="Web Security"/><category term="Web Server"/><category term="WebRTC"/><category term="WebSocket"/><category term="WhatsApp"/><category term="Window Resize"/><category term="Windows"/><category term="Windows 7"/><category term="Wordpress"/><category term="Writing"/><category term="Xco"/><category term="Z-index"/><category term="ZenCart"/><category term="ZeusCart"/><category term="auto suggest text box"/><category term="billing"/><category term="combo box"/><category term="horizontal"/><category term="iPA"/><category term="iTunes"/><category term="kublet"/><category term="multilingual"/><category term="opencart"/><category term="osCommerce"/><category term="osTicket"/><category term="quickfix"/><category term="sortable"/><category term="vertical"/><category term="xampp"/><title type='text'>Hiren&#39;s Technical Blog</title><subtitle type='html'>I am a developer and I know how hard it is to solve difficult issues while programming in case you did not get any help. I have faced this so many times. That&#39;s why I started this blog so that I can share problems and solutions with developer community. In case if you face any issue in programming do check my blog once, it will surely save your time. </subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://www.hiren.dev/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default?redirect=false'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default?start-index=26&amp;max-results=25&amp;redirect=false'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>343</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-74873680006136094</id><published>2026-09-20T11:36:45.774+05:30</published><updated>2026-09-20T11:36:45.775+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="API"/><category scheme="http://www.blogger.com/atom/ns#" term="Certificate Chain"/><category scheme="http://www.blogger.com/atom/ns#" term="Cybersecurity"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="HTTPS"/><category scheme="http://www.blogger.com/atom/ns#" term="Intermediate Certificate"/><category scheme="http://www.blogger.com/atom/ns#" term="Mobile App"/><category scheme="http://www.blogger.com/atom/ns#" term="Nginx"/><category scheme="http://www.blogger.com/atom/ns#" term="OpenSSL"/><category scheme="http://www.blogger.com/atom/ns#" term="SSL"/><category scheme="http://www.blogger.com/atom/ns#" term="SSL Certificate"/><category scheme="http://www.blogger.com/atom/ns#" term="Troubleshooting"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Security"/><title type='text'>Why HTTPS Works in Browser but Fails in Mobile Apps: Understanding SSL Certificate Chains</title><content type='html'>&lt;h1&gt;Why HTTPS Works in a Browser but Fails in a Mobile App&lt;/h1&gt;&lt;p&gt;A few days ago, I came across an interesting issue in a UAT environment.&lt;/p&gt;&lt;p&gt;The API URL was working perfectly fine when accessed through a browser, but the same API was failing from a mobile application.&lt;/p&gt;&lt;p&gt;At first glance, it looked like a mobile application issue.&lt;/p&gt;&lt;p&gt;But it wasn&#39;t.&lt;/p&gt;&lt;p&gt;The actual problem was with the SSL certificate chain configured on the server.&lt;/p&gt;&lt;p&gt;This is one of those issues that can waste quite a bit of time because everything looks fine when you test it from a browser.&lt;/p&gt;&lt;h2&gt;The confusing part&lt;/h2&gt;&lt;p&gt;Let&#39;s say our API is:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;https://api.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;When we opened the URL in a browser, there was no obvious SSL warning. HTTPS looked perfectly fine.&lt;/p&gt;&lt;p&gt;But the mobile application couldn&#39;t establish the connection.&lt;/p&gt;&lt;p&gt;That raised the usual questions:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Is something wrong with the API?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Is the mobile app using the wrong URL?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Is there a network issue?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Is the SSL certificate expired?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Is the backend rejecting the request?&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The certificate itself was valid.&lt;/p&gt;&lt;p&gt;The problem was that the server wasn&#39;t presenting the complete certificate chain.&lt;/p&gt;&lt;h2&gt;What is a certificate chain?&lt;/h2&gt;&lt;p&gt;An SSL/TLS certificate isn&#39;t always a standalone certificate.&lt;/p&gt;&lt;p&gt;There is usually a chain of trust involved:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Your Domain Certificate
        ↓
Intermediate CA
        ↓
Root CA
        ↓
Client Trust Store
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;*.example.com
      ↓
Intermediate CA
      ↓
Root CA
      ↓
Trusted by the client
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The domain certificate identifies the server.&lt;/p&gt;&lt;p&gt;The intermediate certificate provides the link between the server certificate and the trusted root.&lt;/p&gt;&lt;p&gt;That link is important.&lt;/p&gt;&lt;h2&gt;Why can the browser still work?&lt;/h2&gt;&lt;p&gt;This is probably the part that causes the most confusion.&lt;/p&gt;&lt;p&gt;A browser may already have the required intermediate certificate available, or it may be able to retrieve it when necessary.&lt;/p&gt;&lt;p&gt;So you can end up with a situation like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Browser
   ↓
Server Certificate
   ↓
Finds intermediate certificate
   ↓
Connection works
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Another client may not behave the same way:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Mobile App
   ↓
Server Certificate
   ↓
Cannot build complete trust chain
   ↓
TLS validation fails
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;So the fact that Chrome can open your website doesn&#39;t necessarily prove that every HTTPS client will be able to establish the connection.&lt;/p&gt;&lt;p&gt;That&#39;s what makes certificate-chain issues particularly confusing.&lt;/p&gt;&lt;h2&gt;Certificate vs Full Chain&lt;/h2&gt;&lt;p&gt;When you purchase or renew an SSL certificate, your certificate provider may give you several files.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;example.crt
example.key
example.ca-bundle
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code inline=&quot;&quot;&gt;.crt&lt;/code&gt; is the server/domain certificate.&lt;/p&gt;&lt;p&gt;The &lt;code inline=&quot;&quot;&gt;.key&lt;/code&gt; is the private key.&lt;/p&gt;&lt;p&gt;The &lt;code inline=&quot;&quot;&gt;.ca-bundle&lt;/code&gt; contains the CA certificates required to build the trust chain.&lt;/p&gt;&lt;p&gt;The private key stays separate.&lt;/p&gt;&lt;p&gt;For Nginx, you generally create a full-chain file containing the server certificate followed by the required intermediate certificates.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;cat example.crt example.ca-bundle &amp;gt; fullchain.pem
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The important thing is the order:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Server Certificate
        ↓
Intermediate Certificate
        ↓
Additional Intermediate Certificate
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You shouldn&#39;t simply assume that every certificate in a CA bundle needs to be sent by the server. Inspect the bundle and follow the CA provider&#39;s recommended chain.&lt;/p&gt;&lt;h2&gt;Don&#39;t just trust the file — verify it&lt;/h2&gt;&lt;p&gt;One of the useful tools for troubleshooting SSL problems is OpenSSL.&lt;/p&gt;&lt;p&gt;You can inspect the certificates in a CA bundle with:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl crl2pkcs7 -nocrl \
  -certfile example.ca-bundle | \
  openssl pkcs7 -print_certs -noout
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This helps you understand:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Who issued the certificate&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Which intermediate CA is being used&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Which root CA is involved&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;How the certificate hierarchy is structured&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;You can also verify the certificate chain:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl verify -show_chain \
  -CAfile example.ca-bundle \
  example.crt
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A successful result should look something like:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;example.crt: OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That&#39;s much better than simply assuming the certificate is correct because the browser doesn&#39;t show a warning.&lt;/p&gt;&lt;h2&gt;Verify the certificate and private key&lt;/h2&gt;&lt;p&gt;Another check I always recommend is making sure the certificate and private key actually belong together.&lt;/p&gt;&lt;p&gt;For RSA certificates, you can compare their modulus hashes:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl x509 -noout -modulus \
  -in example.crt | openssl sha256
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;And:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl rsa -noout -modulus \
  -in example.key | openssl sha256
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The hashes should match.&lt;/p&gt;&lt;h2&gt;Configure Nginx&lt;/h2&gt;&lt;p&gt;Once the correct full chain has been prepared, Nginx should point to it.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate     /etc/nginx/ssl/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/example.key;

    ...
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The important part is:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;ssl_certificate /etc/nginx/ssl/fullchain.pem;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;rather than pointing only to the domain certificate.&lt;/p&gt;&lt;p&gt;After making the change:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything looks good:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;But how do you know what the server is actually sending?&lt;/h2&gt;&lt;p&gt;This is another important lesson.&lt;/p&gt;&lt;p&gt;Checking the certificate files on the server isn&#39;t enough.&lt;/p&gt;&lt;p&gt;You need to check what the server is actually presenting to clients.&lt;/p&gt;&lt;p&gt;OpenSSL can do this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl s_client \
  -connect api.example.com:443 \
  -servername api.example.com \
  -showcerts &amp;lt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Look for:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Certificate chain
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You should see the server certificate followed by the required intermediate certificates.&lt;/p&gt;&lt;p&gt;More importantly, look for:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Verification: OK
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;and:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Verify return code: 0 (ok)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This gives you much stronger evidence that the live HTTPS endpoint is presenting a usable certificate chain.&lt;/p&gt;&lt;h2&gt;What about mobile applications?&lt;/h2&gt;&lt;p&gt;It&#39;s important not to conclude that every SSL issue in a mobile application is a server issue.&lt;/p&gt;&lt;p&gt;Mobile applications can have their own TLS-related problems, including:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Certificate pinning&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Custom trust stores&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Network security configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Outdated device CA certificates&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;TLS version compatibility&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Incorrect hostname validation&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Proxy configuration&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;So if the server chain is correct and the mobile application still fails, the next step is to investigate the application&#39;s TLS configuration.&lt;/p&gt;&lt;p&gt;The key is to check both sides instead of immediately assuming one is responsible.&lt;/p&gt;&lt;h2&gt;A simple troubleshooting checklist&lt;/h2&gt;&lt;p&gt;When an HTTPS API works in a browser but fails from a mobile application, I usually check these in order:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;✓ Certificate expiry
✓ Domain name / SAN
✓ Certificate and private key match
✓ Intermediate certificates
✓ Certificate chain
✓ What the server actually sends
✓ TLS configuration
✓ Mobile certificate pinning
✓ Mobile network security configuration
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A few OpenSSL commands can answer most of the server-side questions very quickly.&lt;/p&gt;&lt;h2&gt;The bigger lesson&lt;/h2&gt;&lt;p&gt;SSL problems are often misunderstood because we tend to think about HTTPS as:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Certificate + Private Key = HTTPS
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In reality, there is a trust relationship involved:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;                Server
                  │
                  ▼
          Domain Certificate
                  │
                  ▼
           Intermediate CA
                  │
                  ▼
              Root CA
                  │
                  ▼
          Client Trust Store
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the server doesn&#39;t provide the certificates required to build that chain, different clients may behave differently.&lt;/p&gt;&lt;p&gt;That&#39;s why an HTTPS endpoint should be tested from the actual clients that consume it, not just from a browser.&lt;/p&gt;&lt;p&gt;A valid SSL certificate doesn&#39;t necessarily mean that your HTTPS server is correctly configured.&lt;/p&gt;&lt;p&gt;When an API works in a browser but fails in a mobile application, don&#39;t immediately start debugging the application code.&lt;/p&gt;&lt;p&gt;First, check the certificate chain.&lt;/p&gt;&lt;p&gt;Check what certificates the server is actually sending.&lt;/p&gt;&lt;p&gt;And verify the chain using OpenSSL.&lt;/p&gt;&lt;p&gt;A simple command like this can often reveal the problem:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl s_client \
  -connect api.example.com:443 \
  -servername api.example.com \
  -showcerts &amp;lt;/dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The lesson is simple:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Don&#39;t just check whether the certificate is valid. Check whether the complete trust chain is being served correctly.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;Sometimes a small SSL configuration issue on the server can look like a completely unrelated mobile application problem.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/74873680006136094/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/09/why-https-works-in-browser-but-fails-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/74873680006136094'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/74873680006136094'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/09/why-https-works-in-browser-but-fails-in.html' title='Why HTTPS Works in Browser but Fails in Mobile Apps: Understanding SSL Certificate Chains'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-9165648659045653719</id><published>2026-08-30T23:07:59.370+05:30</published><updated>2026-08-30T23:07:59.370+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="API Keys"/><category scheme="http://www.blogger.com/atom/ns#" term="API Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Application Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Code Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Cybersecurity"/><category scheme="http://www.blogger.com/atom/ns#" term="DevSecOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Git Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Secrets Management"/><category scheme="http://www.blogger.com/atom/ns#" term="Secure Coding"/><category scheme="http://www.blogger.com/atom/ns#" term="Vulnerability Management"/><title type='text'>Hardcoded API Keys in Source Code: How to Find, Fix and Prevent Credential Leaks</title><content type='html'>&lt;p&gt;During one of our recent architectural assessments, we were reviewing a client&#39;s application with a broader objective than just understanding the architecture.&lt;/p&gt;&lt;p&gt;As part of the assessment, we were also looking at some of the security and operational practices around the application. While going through the codebases, we came across something that immediately caught our attention: there were API keys and other credentials present directly in the source code.&lt;/p&gt;&lt;p&gt;Finding a key in a codebase may look like a small issue, especially if the application is working correctly. But from a security perspective, it can become a much bigger problem depending on what the key provides access to, where the code is stored and who can access the repository.&lt;/p&gt;&lt;p&gt;We highlighted the finding as part of our assessment.&lt;/p&gt;&lt;p&gt;The client later rotated the affected keys based on our recommendation.&lt;/p&gt;&lt;p&gt;This is a good example of why architectural assessments should not only focus on application structure and technology choices. We should also look for security practices that can create operational risks later.&lt;/p&gt;&lt;p&gt;In this article, we will look at why hardcoded credentials are a problem, how we can identify them, what should happen after finding one, and how we can prevent similar issues from reaching the codebase again.&lt;/p&gt;&lt;h2&gt;Why Are Hardcoded API Keys a Problem?&lt;/h2&gt;&lt;p&gt;An API key is effectively a credential.&lt;/p&gt;&lt;p&gt;Depending on the system, it may provide access to APIs, cloud services, databases, third-party platforms or other resources.&lt;/p&gt;&lt;p&gt;When the key is stored directly in source code, anyone who can access that code may potentially access the credential as well.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;String API_KEY = &quot;xxxxxxxxxxxxxxxx&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Or:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const apiKey = &quot;xxxxxxxxxxxxxxxx&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The problem becomes even more serious when the repository is accessible to a larger engineering team, external contractors or third-party systems.&lt;/p&gt;&lt;p&gt;If the repository is public, the situation becomes significantly more serious because the credential may already be exposed to the internet.&lt;/p&gt;&lt;p&gt;Even when the repository is private, we shouldn&#39;t assume that the credential is safe forever.&lt;/p&gt;&lt;p&gt;Repositories get copied.&lt;/p&gt;&lt;p&gt;Code gets forked.&lt;/p&gt;&lt;p&gt;Developers download source code to their machines.&lt;/p&gt;&lt;p&gt;Backups are created.&lt;/p&gt;&lt;p&gt;CI/CD systems access repositories.&lt;/p&gt;&lt;p&gt;The more places the source code exists, the more difficult it becomes to control the exposure of a credential embedded inside it.&lt;/p&gt;&lt;h2&gt;How Do We Find Hardcoded Credentials?&lt;/h2&gt;&lt;p&gt;The first step is identifying whether credentials are present in the codebase.&lt;/p&gt;&lt;p&gt;A simple search can sometimes reveal obvious cases.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;grep -Rni &quot;api_key&quot; .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can search for other common patterns:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;grep -Rni &quot;apikey&quot; .
grep -Rni &quot;api-key&quot; .
grep -Rni &quot;password&quot; .
grep -Rni &quot;secret&quot; .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, simple text searches aren&#39;t enough.&lt;/p&gt;&lt;p&gt;Developers may use different variable names, encoded values or configuration formats.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
CLIENT_SECRET
PRIVATE_KEY
AUTH_TOKEN
DATABASE_PASSWORD
ACCESS_TOKEN
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is why dedicated secret-scanning tools are useful.&lt;/p&gt;&lt;p&gt;Tools such as Gitleaks, TruffleHog and other security scanners can look for patterns that resemble credentials and secrets.&lt;/p&gt;&lt;p&gt;We can also use Trivy for secret scanning as part of our security checks.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy fs --scanners secret .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The objective isn&#39;t to blindly treat every finding as a confirmed credential. The result needs to be reviewed and validated.&lt;/p&gt;&lt;h2&gt;Finding a Secret Doesn&#39;t Mean the Investigation Is Finished&lt;/h2&gt;&lt;p&gt;This is probably the most important part.&lt;/p&gt;&lt;p&gt;Suppose we find an API key in a source file.&lt;/p&gt;&lt;p&gt;Removing the line from the code doesn&#39;t solve the problem.&lt;/p&gt;&lt;p&gt;We first need to understand whether the credential was actually exposed and whether it is still active.&lt;/p&gt;&lt;p&gt;A useful investigation starts with questions such as:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;What system does the key provide access to?&lt;/li&gt;&lt;li&gt;What permissions does the key have?&lt;/li&gt;&lt;li&gt;Is the key still active?&lt;/li&gt;&lt;li&gt;Who has access to the repository?&lt;/li&gt;&lt;li&gt;Is the repository public or private?&lt;/li&gt;&lt;li&gt;Was the key committed to Git?&lt;/li&gt;&lt;li&gt;Does the key exist in Git history?&lt;/li&gt;&lt;li&gt;Was the key copied into another repository?&lt;/li&gt;&lt;li&gt;Is the key present in build artifacts or deployment packages?&lt;/li&gt;&lt;li&gt;Could the key have been exposed through logs?&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;p&gt;The answers determine the severity and the next steps.&lt;/p&gt;&lt;h2&gt;Don&#39;t Just Delete the Key&lt;/h2&gt;&lt;p&gt;One of the most common mistakes is simply removing the credential from the source file.&lt;/p&gt;&lt;p&gt;For example, changing:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const apiKey = &quot;xxxxxxxxxxxxxxxx&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;to:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const apiKey = &quot;&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;doesn&#39;t invalidate the original credential.&lt;/p&gt;&lt;p&gt;If someone already has the key, deleting it from the current version of the source code doesn&#39;t take away their access.&lt;/p&gt;&lt;p&gt;The credential itself needs to be revoked or rotated.&lt;/p&gt;&lt;h2&gt;Rotate the Credential&lt;/h2&gt;&lt;p&gt;Once we confirm that a credential has been exposed, the next step should generally be to rotate or revoke it.&lt;/p&gt;&lt;p&gt;The exact process depends on the system that issued the credential.&lt;/p&gt;&lt;p&gt;For example, if the key belongs to a third-party API, we should use that provider&#39;s credential management system to revoke the existing key and generate a new one.&lt;/p&gt;&lt;p&gt;The new credential should then be stored outside the source code.&lt;/p&gt;&lt;p&gt;In our assessment, this was the action taken by the client after we highlighted the finding. The affected keys were rotated based on our recommendation.&lt;/p&gt;&lt;p&gt;This is an important distinction between identifying a security issue and actually reducing the security risk.&lt;/p&gt;&lt;h2&gt;What About Git History?&lt;/h2&gt;&lt;p&gt;There is another important detail that is easy to miss.&lt;/p&gt;&lt;p&gt;Removing the credential from the latest version of the source code doesn&#39;t necessarily remove it from Git history.&lt;/p&gt;&lt;p&gt;Consider this sequence:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Commit 1
API key added

Commit 2
Application changes

Commit 3
API key removed
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The key may no longer exist in the latest version of the code, but it may still exist in Commit 1.&lt;/p&gt;&lt;p&gt;Anyone with access to the repository history may still be able to retrieve it.&lt;/p&gt;&lt;p&gt;This is why we should treat an exposed credential as compromised even if the key has already been removed from the current source code.&lt;/p&gt;&lt;p&gt;Rotating the credential is therefore much more important than simply removing the text from the repository.&lt;/p&gt;&lt;h2&gt;Store Secrets Outside the Source Code&lt;/h2&gt;&lt;p&gt;Once we&#39;ve removed the hardcoded credential, we need somewhere appropriate to store it.&lt;/p&gt;&lt;p&gt;The application should retrieve the secret from a secure configuration or secret-management system at runtime.&lt;/p&gt;&lt;p&gt;Depending on the environment, this could be:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Cloud secret management services&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;HashiCorp Vault&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes Secrets&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;CI/CD secret stores&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Environment-specific configuration systems&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The important principle is that credentials shouldn&#39;t be part of the application source code.&lt;/p&gt;&lt;p&gt;For example, instead of:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const apiKey = &quot;xxxxxxxxxxxxxxxx&quot;;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;the application should retrieve the value from its runtime configuration.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const apiKey = process.env.API_KEY;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The exact implementation will depend on the application and deployment environment.&lt;/p&gt;&lt;h2&gt;Be Careful With Environment Variables&lt;/h2&gt;&lt;p&gt;Moving a secret from source code to an environment variable is an improvement, but environment variables aren&#39;t automatically a complete secrets-management solution.&lt;/p&gt;&lt;p&gt;We still need to consider:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Who can view the environment?&lt;/li&gt;&lt;li&gt;Where is the environment variable configured?&lt;/li&gt;&lt;li&gt;Is it visible in CI/CD logs?&lt;/li&gt;&lt;li&gt;Is it stored securely?&lt;/li&gt;&lt;li&gt;Can developers retrieve it unnecessarily?&lt;/li&gt;&lt;li&gt;Is it exposed through debugging or error messages?&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;p&gt;The goal should be controlled access to secrets, not simply moving the secret from one location to another.&lt;/p&gt;&lt;h2&gt;Add Secret Scanning to CI/CD&lt;/h2&gt;&lt;p&gt;Finding a credential during an architectural assessment is useful.&lt;/p&gt;&lt;p&gt;Finding it automatically before the code is merged is even better.&lt;/p&gt;&lt;p&gt;We can introduce secret scanning into the CI/CD pipeline.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Developer
   ↓
Commit
   ↓
Pull Request
   ↓
Secret Scan
   ↓
Build
   ↓
Tests
   ↓
Security Scan
   ↓
Deploy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If a potential credential is detected, the pipeline can stop and require the issue to be reviewed.&lt;/p&gt;&lt;p&gt;This moves security closer to the developer and reduces the chance that credentials make their way into production repositories.&lt;/p&gt;&lt;h2&gt;Scan More Than Just the Current Code&lt;/h2&gt;&lt;p&gt;A common mistake is scanning only the current working directory.&lt;/p&gt;&lt;p&gt;For repositories with a long history, we should also consider Git history.&lt;/p&gt;&lt;p&gt;A secret may have been committed months ago and removed later.&lt;/p&gt;&lt;p&gt;Depending on the tool we&#39;re using, we can scan repository history to identify credentials that may have existed in previous commits.&lt;/p&gt;&lt;p&gt;This is especially important when performing a security or architectural assessment on an existing application.&lt;/p&gt;&lt;h2&gt;Common Places Where Secrets Hide&lt;/h2&gt;&lt;p&gt;During assessments, we shouldn&#39;t look only for obvious API key variables.&lt;/p&gt;&lt;p&gt;Secrets can appear in many places.&lt;/p&gt;&lt;p&gt;Some common examples include:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Source code&lt;/li&gt;&lt;li&gt;Configuration files&lt;/li&gt;&lt;li&gt;&lt;code inline=&quot;&quot;&gt;.env&lt;/code&gt; files&lt;/li&gt;&lt;li&gt;Dockerfiles&lt;/li&gt;&lt;li&gt;Docker Compose files&lt;/li&gt;&lt;li&gt;Kubernetes manifests&lt;/li&gt;&lt;li&gt;CI/CD configuration&lt;/li&gt;&lt;li&gt;Infrastructure as Code&lt;/li&gt;&lt;li&gt;Scripts&lt;/li&gt;&lt;li&gt;Documentation&lt;/li&gt;&lt;li&gt;Test configuration&lt;/li&gt;&lt;li&gt;Sample configuration files&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;p&gt;Even documentation can accidentally contain a real credential if developers copy production configuration while creating examples.&lt;/p&gt;&lt;h2&gt;What About Configuration Files?&lt;/h2&gt;&lt;p&gt;Configuration files are another common place for credentials.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;database:
  username: admin
  password: mypassword
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This might not look like source code, but it can create exactly the same security problem.&lt;/p&gt;&lt;p&gt;Configuration should therefore be included in security scanning and code reviews.&lt;/p&gt;&lt;h2&gt;Don&#39;t Ignore Test Credentials&lt;/h2&gt;&lt;p&gt;Test environments also deserve attention.&lt;/p&gt;&lt;p&gt;Teams sometimes assume that test credentials are harmless because they don&#39;t provide access to production.&lt;/p&gt;&lt;p&gt;That isn&#39;t always true.&lt;/p&gt;&lt;p&gt;A test credential may still provide access to customer information, internal systems or paid third-party services.&lt;/p&gt;&lt;p&gt;We should understand what every credential can access rather than assuming that a credential is safe simply because it belongs to a non-production environment.&lt;/p&gt;&lt;h2&gt;A Practical Response Process&lt;/h2&gt;&lt;p&gt;When we discover a credential in a codebase, the following process provides a good starting point.&lt;/p&gt;&lt;h3&gt;1. Identify the Credential&lt;/h3&gt;&lt;p&gt;Determine what the credential belongs to and what system it can access.&lt;/p&gt;&lt;h3&gt;2. Assess the Exposure&lt;/h3&gt;&lt;p&gt;Check where the credential exists and who could potentially access it.&lt;/p&gt;&lt;h3&gt;3. Check Whether It Is Active&lt;/h3&gt;&lt;p&gt;An old or revoked credential may not create the same level of risk as an active credential.&lt;/p&gt;&lt;h3&gt;4. Review Its Permissions&lt;/h3&gt;&lt;p&gt;A read-only API key is different from a credential with administrative access.&lt;/p&gt;&lt;h3&gt;5. Rotate or Revoke It&lt;/h3&gt;&lt;p&gt;If the credential is active and exposed, rotate or revoke it as quickly as possible.&lt;/p&gt;&lt;h3&gt;6. Remove It From the Code&lt;/h3&gt;&lt;p&gt;Remove the credential from the current source code and configuration.&lt;/p&gt;&lt;h3&gt;7. Review Git History&lt;/h3&gt;&lt;p&gt;Determine whether the credential exists in previous commits.&lt;/p&gt;&lt;h3&gt;8. Move the Secret to Proper Secret Management&lt;/h3&gt;&lt;p&gt;Use the appropriate secret-management mechanism for the environment.&lt;/p&gt;&lt;h3&gt;9. Add Preventive Controls&lt;/h3&gt;&lt;p&gt;Introduce secret scanning into developer workflows and CI/CD.&lt;/p&gt;&lt;p&gt;This process helps us move from simply identifying a security finding to actually reducing the risk.&lt;/p&gt;&lt;h2&gt;Common Mistakes&lt;/h2&gt;&lt;p&gt;There are a few mistakes we should avoid.&lt;/p&gt;&lt;h3&gt;Deleting the Credential and Moving On&lt;/h3&gt;&lt;p&gt;Removing the credential from the latest source code doesn&#39;t invalidate it.&lt;/p&gt;&lt;p&gt;We need to rotate or revoke the credential.&lt;/p&gt;&lt;h3&gt;Assuming Private Repositories Are Safe&lt;/h3&gt;&lt;p&gt;Private repositories reduce exposure, but they don&#39;t eliminate it.&lt;/p&gt;&lt;p&gt;Access should still be controlled.&lt;/p&gt;&lt;h3&gt;Storing Secrets in Configuration Files&lt;/h3&gt;&lt;p&gt;Moving a password from source code into a committed configuration file doesn&#39;t solve the underlying problem.&lt;/p&gt;&lt;p&gt;The configuration file is still part of the codebase.&lt;/p&gt;&lt;h3&gt;Putting Secrets in CI/CD Logs&lt;/h3&gt;&lt;p&gt;Even when credentials aren&#39;t stored in source code, they can accidentally appear in build logs.&lt;/p&gt;&lt;p&gt;We should make sure sensitive variables are masked and never printed.&lt;/p&gt;&lt;h3&gt;Giving Credentials More Permissions Than Necessary&lt;/h3&gt;&lt;p&gt;If an application only needs read access to a service, the credential shouldn&#39;t have administrative privileges.&lt;/p&gt;&lt;p&gt;The principle of least privilege should apply to application credentials as well.&lt;/p&gt;&lt;h2&gt;What We Should Check During an Architectural Assessment&lt;/h2&gt;&lt;p&gt;When performing an architectural assessment, security shouldn&#39;t be limited to reviewing authentication and network diagrams.&lt;/p&gt;&lt;p&gt;A practical assessment should also include questions around:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Where are application secrets stored?&lt;/li&gt;&lt;li&gt;How are credentials managed?&lt;/li&gt;&lt;li&gt;Who can access production secrets?&lt;/li&gt;&lt;li&gt;Are secrets stored in source control?&lt;/li&gt;&lt;li&gt;Is Git history scanned?&lt;/li&gt;&lt;li&gt;Are secrets scanned during CI/CD?&lt;/li&gt;&lt;li&gt;How are credentials rotated?&lt;/li&gt;&lt;li&gt;What happens when a credential is compromised?&lt;/li&gt;&lt;li&gt;Are application credentials granted excessive permissions?&lt;/li&gt;&lt;li&gt;Are secrets exposed in logs or monitoring systems?&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;p&gt;These questions can uncover risks that may not be visible from architecture diagrams alone.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/9165648659045653719/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/08/hardcoded-api-keys-in-source-code-how.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/9165648659045653719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/9165648659045653719'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/08/hardcoded-api-keys-in-source-code-how.html' title='Hardcoded API Keys in Source Code: How to Find, Fix and Prevent Credential Leaks'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-6986459735353257464</id><published>2026-08-30T22:39:48.990+05:30</published><updated>2026-08-30T22:39:48.990+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Application Security"/><category scheme="http://www.blogger.com/atom/ns#" term="CI/CD"/><category scheme="http://www.blogger.com/atom/ns#" term="Container Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Cybersecurity"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="DevSecOps"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="Open Source Security"/><category scheme="http://www.blogger.com/atom/ns#" term="Trivy"/><category scheme="http://www.blogger.com/atom/ns#" term="Vulnerability Scanning"/><title type='text'>Trivy in CI/CD: How to Add Vulnerability Scanning to Your Pipeline</title><content type='html'>&lt;p&gt;Security testing shouldn&#39;t start after an application reaches production.&lt;/p&gt;&lt;p&gt;If we are already using CI/CD to build, test and deploy our applications, it makes sense to introduce security checks into the same process. This allows us to identify vulnerabilities before they become production problems.&lt;/p&gt;&lt;p&gt;One of the open-source tools we can use for this is Trivy.&lt;/p&gt;&lt;p&gt;Trivy can scan container images, source code repositories and filesystems for vulnerabilities. It can also identify configuration problems, secrets and other security-related issues.&lt;/p&gt;&lt;p&gt;In this article, we will see how we can introduce Trivy into a CI/CD pipeline, starting with a simple local scan and then moving towards using it as a security gate in our pipeline.&lt;/p&gt;&lt;h2&gt;What Is Trivy?&lt;/h2&gt;&lt;p&gt;Trivy is an open-source security scanner maintained by Aqua Security.&lt;/p&gt;&lt;p&gt;It is commonly used for scanning container images, but it can do much more than that. Depending on how we use it, Trivy can scan:&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Container images&lt;/li&gt;&lt;li&gt;Filesystems&lt;/li&gt;&lt;li&gt;Git repositories&lt;/li&gt;&lt;li&gt;Infrastructure as Code&lt;/li&gt;&lt;li&gt;Kubernetes configurations&lt;/li&gt;&lt;li&gt;Dependencies&lt;/li&gt;&lt;li&gt;Secrets&lt;/li&gt;&lt;li&gt;Licenses&lt;/li&gt;&lt;/ul&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;p&gt;For this article, we will focus mainly on container image vulnerability scanning because it is one of the easiest ways to introduce security scanning into an existing CI/CD process.&lt;/p&gt;&lt;h2&gt;Why Add Vulnerability Scanning to CI/CD?&lt;/h2&gt;&lt;p&gt;Let&#39;s consider a typical application pipeline.&lt;/p&gt;&lt;p&gt;The application is compiled, tests are executed, a Docker image is created and the image is pushed to a container registry. Eventually, that image is deployed to Kubernetes or another production environment.&lt;/p&gt;&lt;p&gt;The problem is that the container image may contain vulnerable operating system packages or application dependencies.&lt;/p&gt;&lt;p&gt;If we only discover those vulnerabilities after deployment, fixing them becomes more complicated.&lt;/p&gt;&lt;p&gt;Instead, we can scan the image before it is pushed or deployed.&lt;/p&gt;&lt;p&gt;A simple pipeline can therefore look like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Code
  ↓
Build
  ↓
Unit Tests
  ↓
Build Docker Image
  ↓
Trivy Scan
  ↓
Push Image
  ↓
Deploy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the vulnerability scan fails, the pipeline stops and the vulnerable image doesn&#39;t move further through the deployment process.&lt;/p&gt;&lt;p&gt;This is the basic idea behind adding security into CI/CD.&lt;/p&gt;&lt;h2&gt;Step 1: Install Trivy&lt;/h2&gt;&lt;p&gt;There are several ways to install Trivy depending on the operating system and environment.&lt;/p&gt;&lt;p&gt;For Ubuntu, we can install it using the official repository.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt-get install wget gnupg
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add the repository signing key:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | \
gpg --dearmor | \
sudo tee /usr/share/keyrings/trivy.gpg &amp;gt; /dev/null
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add the Trivy repository:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;echo &quot;deb [signed-by=/usr/share/keyrings/trivy.gpg] \
https://aquasecurity.github.io/trivy-repo/deb \
generic main&quot; | \
sudo tee /etc/apt/sources.list.d/trivy.list
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Update the package list:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Install Trivy:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt-get install trivy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Verify the installation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy --version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We should see the installed Trivy version in the output.&lt;/p&gt;&lt;p&gt;The installation method may change over time, so it is worth checking the current Trivy documentation if we are setting this up on a new machine.&lt;/p&gt;&lt;h2&gt;Step 2: Scan a Docker Image&lt;/h2&gt;&lt;p&gt;Once Trivy is installed, we can immediately start scanning container images.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image nginx:latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Trivy will download the image if it isn&#39;t already available locally and scan its packages for known vulnerabilities.&lt;/p&gt;&lt;p&gt;The output will contain information such as:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Library        Vulnerability     Severity
openssl        CVE-XXXX-XXXXX    HIGH
curl           CVE-XXXX-XXXXX    MEDIUM
libxyz         CVE-XXXX-XXXXX    CRITICAL
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The exact results will depend on the image version and the vulnerabilities known at the time of the scan.&lt;/p&gt;&lt;p&gt;This is already useful, but we probably don&#39;t want every vulnerability to stop our pipeline.&lt;/p&gt;&lt;h2&gt;Step 3: Scan Only High and Critical Vulnerabilities&lt;/h2&gt;&lt;p&gt;In a CI/CD environment, we usually need to decide which vulnerabilities should block a deployment.&lt;/p&gt;&lt;p&gt;We can filter the results by severity:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image --severity HIGH,CRITICAL nginx:latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This allows us to focus on vulnerabilities that require immediate attention.&lt;/p&gt;&lt;p&gt;However, filtering the displayed results alone doesn&#39;t necessarily make the pipeline fail. We need to explicitly configure the exit code.&lt;/p&gt;&lt;h2&gt;Step 4: Make the Pipeline Fail&lt;/h2&gt;&lt;p&gt;This is where Trivy becomes useful as a CI/CD security gate.&lt;/p&gt;&lt;p&gt;Consider this command:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image \
  --severity HIGH,CRITICAL \
  --exit-code 1 \
  nginx:latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code inline=&quot;&quot;&gt;--exit-code 1&lt;/code&gt; option tells Trivy to return a non-zero exit code when vulnerabilities matching the selected criteria are found.&lt;/p&gt;&lt;p&gt;CI/CD systems generally treat a non-zero exit code as a failed step.&lt;/p&gt;&lt;p&gt;So the behaviour becomes:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;No HIGH/CRITICAL vulnerabilities
        ↓
Pipeline continues

HIGH/CRITICAL vulnerability found
        ↓
Trivy returns exit code 1
        ↓
Pipeline fails
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is the important difference between simply running a security scan and actually making security part of our deployment process.&lt;/p&gt;&lt;h2&gt;Step 5: Scan Our Own Docker Image&lt;/h2&gt;&lt;p&gt;Instead of scanning a public image, let&#39;s assume our pipeline builds an image called:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can scan it using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image --severity HIGH,CRITICAL myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;For CI/CD, we can use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image \
  --severity HIGH,CRITICAL \
  --exit-code 1 \
  myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the scan passes, the pipeline can continue with the next stage.&lt;/p&gt;&lt;p&gt;If the scan finds a HIGH or CRITICAL vulnerability, the pipeline stops.&lt;/p&gt;&lt;h2&gt;Step 6: Ignore Vulnerabilities That Don&#39;t Have a Fix&lt;/h2&gt;&lt;p&gt;This is one area where we need to be careful.&lt;/p&gt;&lt;p&gt;A vulnerability may be known, but there may not yet be a fixed package available.&lt;/p&gt;&lt;p&gt;If we fail the pipeline for every vulnerability regardless of whether a fix exists, developers may quickly start treating the security pipeline as an obstacle rather than a useful control.&lt;/p&gt;&lt;p&gt;Trivy allows us to ignore vulnerabilities for which no fix is currently available.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image \
  --severity HIGH,CRITICAL \
  --ignore-unfixed \
  --exit-code 1 \
  myapp:1.0.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This means we focus the pipeline gate on vulnerabilities where a fix is available.&lt;/p&gt;&lt;p&gt;That doesn&#39;t mean unfixed vulnerabilities should be ignored forever. They should still be tracked and reviewed.&lt;/p&gt;&lt;h2&gt;Step 7: Scanning the Source Code&lt;/h2&gt;&lt;p&gt;Trivy isn&#39;t limited to container images.&lt;/p&gt;&lt;p&gt;We can also scan a project directory:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy fs .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can focus on vulnerabilities:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy fs \
  --scanners vuln \
  .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can also scan for secrets:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy fs \
  --scanners secret \
  .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This can help detect accidentally committed credentials, tokens and other sensitive information.&lt;/p&gt;&lt;p&gt;For example, a developer might accidentally commit a configuration file containing an API key.&lt;/p&gt;&lt;p&gt;A source scan gives us another opportunity to detect the problem before the code reaches production.&lt;/p&gt;&lt;h2&gt;Step 8: Adding Trivy to a CI/CD Pipeline&lt;/h2&gt;&lt;p&gt;Now we can bring everything together.&lt;/p&gt;&lt;p&gt;A simplified pipeline looks like this:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Checkout Code
      ↓
Build Application
      ↓
Run Tests
      ↓
Build Docker Image
      ↓
Trivy Vulnerability Scan
      ↓
Push Image
      ↓
Deploy
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The important part is where we place the security scan.&lt;/p&gt;&lt;p&gt;We should scan the exact image that we are planning to deploy.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker build -t myapp:$BUILD_ID .
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image \
  --severity HIGH,CRITICAL \
  --ignore-unfixed \
  --exit-code 1 \
  myapp:$BUILD_ID
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the scan passes:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker push myapp:$BUILD_ID
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The deployment can then use that exact image.&lt;/p&gt;&lt;p&gt;This gives us a simple security gate before the artifact moves to the next environment.&lt;/p&gt;&lt;h2&gt;Step 9: Generate a Report&lt;/h2&gt;&lt;p&gt;Sometimes we don&#39;t just want the pipeline to pass or fail. We also want a report that developers and security teams can review.&lt;/p&gt;&lt;p&gt;Trivy supports different output formats.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;trivy image \
  --format json \
  --output trivy-report.json \
  myapp:$BUILD_ID
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can then publish the generated report as a CI/CD pipeline artifact.&lt;/p&gt;&lt;p&gt;This is useful because the pipeline result tells us that something failed, while the report tells us what actually needs to be fixed.&lt;/p&gt;&lt;h2&gt;Step 10: Don&#39;t Make Every Vulnerability a Pipeline Failure&lt;/h2&gt;&lt;p&gt;This is where security implementation requires some judgement.&lt;/p&gt;&lt;p&gt;If we configure the pipeline to fail for every LOW, MEDIUM, HIGH and CRITICAL vulnerability from day one, there is a good chance the pipeline will become difficult to use.&lt;/p&gt;&lt;p&gt;A better approach is to establish a security policy.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;LOW       → Report
MEDIUM    → Report and Track
HIGH      → Review / Block
CRITICAL  → Block
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The exact policy will depend on the application and organisation.&lt;/p&gt;&lt;p&gt;For internet-facing applications, we may choose a stricter policy. For internal applications, we may initially use a more gradual approach.&lt;/p&gt;&lt;p&gt;The important thing is to define the policy rather than letting every security finding become an emergency.&lt;/p&gt;&lt;h2&gt;Managing Exceptions&lt;/h2&gt;&lt;p&gt;There will be situations where a vulnerability needs to be accepted temporarily.&lt;/p&gt;&lt;p&gt;Trivy supports ignore files for this purpose.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;.trivyignore
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can place vulnerability IDs in the file that we have deliberately reviewed and accepted.&lt;/p&gt;&lt;p&gt;However, this should be used carefully.&lt;/p&gt;&lt;p&gt;A common mistake is to keep adding vulnerabilities to &lt;code inline=&quot;&quot;&gt;.trivyignore&lt;/code&gt; simply because they are causing pipeline failures.&lt;/p&gt;&lt;p&gt;That defeats the purpose of having the security scan in the first place.&lt;/p&gt;&lt;p&gt;Every exception should have a reason, an owner and, ideally, an expiry or review date.&lt;/p&gt;&lt;h2&gt;Common Mistakes&lt;/h2&gt;&lt;p&gt;There are a few mistakes we should avoid when introducing Trivy into CI/CD.&lt;/p&gt;&lt;h3&gt;Scanning Only in Production&lt;/h3&gt;&lt;p&gt;If we scan only after deployment, we have already allowed the vulnerable artifact into our environment.&lt;/p&gt;&lt;p&gt;Security scanning is more useful when it happens before deployment.&lt;/p&gt;&lt;h3&gt;Blocking Everything Immediately&lt;/h3&gt;&lt;p&gt;Introducing a security gate without understanding the current vulnerability baseline can cause hundreds of existing issues to break the pipeline.&lt;/p&gt;&lt;p&gt;It is often better to establish a baseline first and then gradually increase the enforcement level.&lt;/p&gt;&lt;h3&gt;Ignoring Unfixed Vulnerabilities Forever&lt;/h3&gt;&lt;p&gt;Using &lt;code inline=&quot;&quot;&gt;--ignore-unfixed&lt;/code&gt; can make the pipeline more practical, but it shouldn&#39;t become an excuse to forget about those vulnerabilities.&lt;/p&gt;&lt;p&gt;The vulnerability may receive a fix later.&lt;/p&gt;&lt;h3&gt;Ignoring the Docker Base Image&lt;/h3&gt;&lt;p&gt;Many vulnerabilities come from the base image itself.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-dockerfile&quot;&gt;FROM ubuntu:latest
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The application code may be perfectly secure while the underlying image contains vulnerable packages.&lt;/p&gt;&lt;p&gt;Keeping the base image updated is therefore an important part of container security.&lt;/p&gt;&lt;h3&gt;Treating the Scan as the Final Security Check&lt;/h3&gt;&lt;p&gt;Trivy is a valuable security tool, but it doesn&#39;t replace a complete security program.&lt;/p&gt;&lt;p&gt;Application security also includes:&lt;/p&gt;&lt;p style=&quot;text-align: left;&quot;&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Secure coding&lt;/li&gt;&lt;li&gt;Dependency management&lt;/li&gt;&lt;li&gt;Secrets management&lt;/li&gt;&lt;li&gt;Access control&lt;/li&gt;&lt;li&gt;Network security&lt;/li&gt;&lt;li&gt;Authentication&lt;/li&gt;&lt;li&gt;Authorization&lt;/li&gt;&lt;li&gt;Infrastructure security&lt;/li&gt;&lt;li&gt;Runtime monitoring&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;Trivy should be one layer in the overall security process.&lt;/p&gt;&lt;h2&gt;Where Should We Run the Scan?&lt;/h2&gt;&lt;p&gt;There isn&#39;t one universal answer.&lt;/p&gt;&lt;p&gt;A practical approach is to scan at multiple stages.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Developer Machine
        ↓
Source / Dependency Scan
        ↓
CI Build
        ↓
Container Image Scan
        ↓
Container Registry
        ↓
Deployment
        ↓
Runtime Monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The earlier we identify a problem, the cheaper it usually is to fix.&lt;/p&gt;&lt;p&gt;A vulnerability found during development is much easier to address than one discovered after a production deployment.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/6986459735353257464/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/08/trivy-in-cicd-how-to-add-vulnerability.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6986459735353257464'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6986459735353257464'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/08/trivy-in-cicd-how-to-add-vulnerability.html' title='Trivy in CI/CD: How to Add Vulnerability Scanning to Your Pipeline'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-1406565574179058829</id><published>2026-08-30T22:26:46.809+05:30</published><updated>2026-08-30T22:26:46.809+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Certbot"/><category scheme="http://www.blogger.com/atom/ns#" term="Cloud"/><category scheme="http://www.blogger.com/atom/ns#" term="Cybersecurity"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="HTTPS"/><category scheme="http://www.blogger.com/atom/ns#" term="Let&#39;s Encrypt"/><category scheme="http://www.blogger.com/atom/ns#" term="Linux"/><category scheme="http://www.blogger.com/atom/ns#" term="Nginx"/><category scheme="http://www.blogger.com/atom/ns#" term="SSL"/><category scheme="http://www.blogger.com/atom/ns#" term="SSL Certificate"/><category scheme="http://www.blogger.com/atom/ns#" term="Troubleshooting"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Server"/><title type='text'>How to Set Up Let’s Encrypt SSL Certificate with Nginx</title><content type='html'>&lt;p&gt;If we are hosting a web application on a Linux server, enabling HTTPS is one of the first things we should take care of before exposing the application to users.&lt;/p&gt;&lt;p&gt;One of the easiest ways to do this is by using Let’s Encrypt. It provides free SSL/TLS certificates, and with Certbot we can automate both certificate installation and renewal.&lt;/p&gt;&lt;p&gt;In this article, we will go step by step through the process of configuring a Let’s Encrypt certificate with Nginx. We will also look at certificate renewal and some common issues that can prevent the certificate from being generated or renewed successfully.&lt;/p&gt;&lt;h2&gt;What We Are Going to Set Up&lt;/h2&gt;&lt;p&gt;We will configure Nginx to serve our application over HTTPS using a certificate issued by Let’s Encrypt.&lt;/p&gt;&lt;p&gt;The setup will include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;A domain pointing to our server&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Nginx configured as the web server or reverse proxy&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A Let’s Encrypt SSL certificate&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;HTTPS access on port 443&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;HTTP to HTTPS redirection&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Automatic certificate renewal&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Prerequisites&lt;/h2&gt;&lt;p&gt;For this guide, we will assume that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;We have a Linux server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ubuntu is being used as the operating system.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Nginx is installed or can be installed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;We have a domain name.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;We have access to the DNS configuration for the domain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;We have sudo access to the server.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ports 80 and 443 are accessible from the internet.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For the examples below, we will use:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Domain: example.com
Server IP: 203.0.113.10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Replace these values with the actual domain and server details.&lt;/p&gt;&lt;h2&gt;Step 1: Point the Domain to the Server&lt;/h2&gt;&lt;p&gt;Before requesting an SSL certificate, our domain needs to resolve to the server where Nginx is running.&lt;/p&gt;&lt;p&gt;In the DNS configuration, create an A record.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Type: A
Name: @
Value: 203.0.113.10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we also want to support &lt;code inline=&quot;&quot;&gt;www.example.com&lt;/code&gt;, we can create another record:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Type: A
Name: www
Value: 203.0.113.10
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Depending on the DNS provider, the interface will look different, but the concept remains the same.&lt;/p&gt;&lt;p&gt;We should verify that DNS is resolving correctly before moving forward.&lt;/p&gt;&lt;p&gt;From the server or our local machine, run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;nslookup example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;or:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;dig example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The returned IP address should match our server&#39;s public IP.&lt;/p&gt;&lt;p&gt;If DNS is not resolving correctly, there is no point proceeding with Certbot yet. Let&#39;s Encrypt needs to verify that we control the domain.&lt;/p&gt;&lt;h2&gt;Step 2: Install Nginx&lt;/h2&gt;&lt;p&gt;If Nginx isn&#39;t already installed, we can install it using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install nginx -y
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Once the installation is complete, check the service:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl status nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We should see that the service is running.&lt;/p&gt;&lt;p&gt;We can also verify the configuration:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A successful configuration check should return something similar to:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;syntax is ok
test is successful
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now open the domain in a browser:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;http://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;At this stage, we should get the Nginx default page or our application, depending on how Nginx has been configured.&lt;/p&gt;&lt;h2&gt;Step 3: Configure Nginx for the Domain&lt;/h2&gt;&lt;p&gt;Before requesting the certificate, we should configure a server block for our domain.&lt;/p&gt;&lt;p&gt;Create a configuration file:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nano /etc/nginx/sites-available/example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Add the following:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    listen 80;
    listen [::]:80;

    server_name example.com www.example.com;

    location / {
        proxy_pass http://127.0.0.1:8000;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code inline=&quot;&quot;&gt;proxy_pass&lt;/code&gt; value should point to the application running behind Nginx.&lt;/p&gt;&lt;p&gt;For example, if our application is running on port 3000:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;proxy_pass http://127.0.0.1:3000;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the application is running on another server, we can use that server&#39;s address instead.&lt;/p&gt;&lt;h2&gt;Step 4: Enable the Nginx Configuration&lt;/h2&gt;&lt;p&gt;Create a symbolic link to enable the configuration:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then test the configuration:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything looks correct, reload Nginx:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Now verify that the domain is accessible:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;http://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We should make sure the application works correctly over HTTP before moving to HTTPS.&lt;/p&gt;&lt;h2&gt;Step 5: Install Certbot&lt;/h2&gt;&lt;p&gt;Now we can install Certbot and the Nginx plugin.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install certbot python3-certbot-nginx -y
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Verify the installation:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;certbot --version
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We should get the installed Certbot version as the output.&lt;/p&gt;&lt;p&gt;Certbot will communicate with Let&#39;s Encrypt, request the certificate and configure Nginx for HTTPS.&lt;/p&gt;&lt;h2&gt;Step 6: Request the Let&#39;s Encrypt Certificate&lt;/h2&gt;&lt;p&gt;Now we can request the certificate.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot --nginx -d example.com -d www.example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Certbot will ask for some information, including an email address and agreement to the terms of service.&lt;/p&gt;&lt;p&gt;It will then communicate with Let&#39;s Encrypt and perform domain validation.&lt;/p&gt;&lt;p&gt;If the validation succeeds, Certbot will obtain the certificate and update the Nginx configuration.&lt;/p&gt;&lt;p&gt;One of the advantages of using the Nginx plugin is that we don&#39;t have to manually copy certificate paths into the Nginx configuration.&lt;/p&gt;&lt;h2&gt;Step 7: Redirect HTTP to HTTPS&lt;/h2&gt;&lt;p&gt;During the Certbot setup, we may be asked whether HTTP traffic should be redirected to HTTPS.&lt;/p&gt;&lt;p&gt;Choose the redirect option if we want all HTTP traffic to automatically use HTTPS.&lt;/p&gt;&lt;p&gt;After enabling the redirect, users visiting:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;http://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;will automatically be redirected to:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;https://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This ensures that users always access the application through an encrypted connection.&lt;/p&gt;&lt;h2&gt;Step 8: Verify the HTTPS Configuration&lt;/h2&gt;&lt;p&gt;Open the following URL in a browser:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;https://example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The browser should show the secure connection indicator.&lt;/p&gt;&lt;p&gt;We can also check the certificate from the command line:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl s_client -connect example.com:443 -servername example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This provides information about the certificate and TLS connection.&lt;/p&gt;&lt;p&gt;We can also check the Nginx configuration:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If everything is configured correctly, Nginx should report:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;syntax is ok
test is successful
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Step 9: Check the Certificate&lt;/h2&gt;&lt;p&gt;Certbot provides a convenient command to check the certificates currently installed on the server.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot certificates
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example output:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Certificate Name: example.com
Domains: example.com www.example.com
Expiry Date: ...
Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem
Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Certbot normally stores certificates under:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;/etc/letsencrypt/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We generally shouldn&#39;t manually modify files inside this directory because Certbot manages the certificate lifecycle.&lt;/p&gt;&lt;h2&gt;Step 10: Configure Automatic Renewal&lt;/h2&gt;&lt;p&gt;Let&#39;s Encrypt certificates are short-lived and need to be renewed regularly.&lt;/p&gt;&lt;p&gt;The good part is that Certbot can handle renewal automatically.&lt;/p&gt;&lt;p&gt;First, check whether the Certbot renewal timer is active:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl status certbot.timer
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We can also check the timers on the system:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;systemctl list-timers | grep certbot
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the timer is configured correctly, Certbot will periodically check whether the certificate needs renewal.&lt;/p&gt;&lt;h2&gt;Step 11: Test Certificate Renewal&lt;/h2&gt;&lt;p&gt;We shouldn&#39;t wait until the certificate is about to expire to find out that automatic renewal doesn&#39;t work.&lt;/p&gt;&lt;p&gt;We can perform a dry run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot renew --dry-run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This performs a simulated renewal process without replacing the existing certificate.&lt;/p&gt;&lt;p&gt;A successful test should indicate that the renewal simulation completed successfully.&lt;/p&gt;&lt;p&gt;This is something worth testing after the initial setup and whenever we make significant changes to the Nginx or DNS configuration.&lt;/p&gt;&lt;h2&gt;Common Problems&lt;/h2&gt;&lt;p&gt;The installation itself is usually straightforward. Most problems occur during domain validation, Nginx configuration or certificate renewal.&lt;/p&gt;&lt;h3&gt;Problem 1: Domain Doesn&#39;t Point to the Server&lt;/h3&gt;&lt;p&gt;If Certbot reports that domain validation failed, the first thing we should check is DNS.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;dig example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Make sure the returned IP address points to the correct server.&lt;/p&gt;&lt;p&gt;If DNS was changed recently, we may also need to wait for the DNS changes to propagate.&lt;/p&gt;&lt;h3&gt;Problem 2: Port 80 Is Not Accessible&lt;/h3&gt;&lt;p&gt;Let&#39;s Encrypt commonly needs to reach the server through HTTP during certificate validation.&lt;/p&gt;&lt;p&gt;Make sure port 80 is open.&lt;/p&gt;&lt;p&gt;On Ubuntu with UFW:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw status
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If required:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the server is running in a cloud environment, we also need to check the cloud firewall or security group.&lt;/p&gt;&lt;p&gt;Opening the port in UFW isn&#39;t enough if the cloud firewall is blocking the traffic.&lt;/p&gt;&lt;h3&gt;Problem 3: Nginx Configuration Test Fails&lt;/h3&gt;&lt;p&gt;If this command fails:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;we should fix the Nginx configuration before running Certbot.&lt;/p&gt;&lt;p&gt;The error message usually contains the configuration file and line number where the problem exists.&lt;/p&gt;&lt;p&gt;We can inspect the complete configuration using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -T
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This prints the complete Nginx configuration currently being loaded.&lt;/p&gt;&lt;h3&gt;Problem 4: Too Many Redirects&lt;/h3&gt;&lt;p&gt;After enabling HTTPS, we may sometimes encounter a redirect loop.&lt;/p&gt;&lt;p&gt;For example, the browser keeps switching between HTTP and HTTPS.&lt;/p&gt;&lt;p&gt;This usually happens when there is another reverse proxy or load balancer in front of Nginx and the original protocol isn&#39;t being handled correctly.&lt;/p&gt;&lt;p&gt;We should check:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Nginx redirect rules&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Reverse proxy configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Load balancer configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code inline=&quot;&quot;&gt;X-Forwarded-Proto&lt;/code&gt; headers&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;We should avoid adding multiple layers of HTTPS redirects without understanding how traffic flows through the infrastructure.&lt;/p&gt;&lt;h3&gt;Problem 5: Certificate Renewal Fails&lt;/h3&gt;&lt;p&gt;If automatic renewal fails, first check the existing certificates:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot certificates
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Then test renewal manually:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot renew --dry-run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check the Certbot logs if the problem isn&#39;t obvious:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo ls /var/log/letsencrypt/
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The logs usually provide enough information to identify whether the issue is DNS, Nginx, port accessibility or certificate validation.&lt;/p&gt;&lt;h2&gt;Useful Commands&lt;/h2&gt;&lt;p&gt;Here are some commands we can keep handy when troubleshooting a Let&#39;s Encrypt and Nginx setup.&lt;/p&gt;&lt;p&gt;Check Nginx status:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl status nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Test Nginx configuration:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Reload Nginx:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check certificates:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot certificates
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Test renewal:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo certbot renew --dry-run
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check Certbot timer:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;systemctl list-timers | grep certbot
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check HTTPS certificate:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;openssl s_client -connect example.com:443 -servername example.com
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Check DNS:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;dig example.com
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;A Few Things We Should Keep in Mind&lt;/h2&gt;&lt;p&gt;Getting the certificate is only one part of enabling HTTPS.&lt;/p&gt;&lt;p&gt;We should also make sure that:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;HTTP redirects to HTTPS.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Port 443 is accessible.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The certificate covers all required domains.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Automatic renewal is working.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Nginx configuration remains valid.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Application URLs use HTTPS where required.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mixed-content issues are not introduced in the application.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;HTTPS should be treated as part of the application&#39;s infrastructure rather than simply a certificate that we install once and forget about.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/1406565574179058829/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/08/how-to-set-up-lets-encrypt-ssl.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1406565574179058829'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1406565574179058829'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/08/how-to-set-up-lets-encrypt-ssl.html' title='How to Set Up Let’s Encrypt SSL Certificate with Nginx'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-2101354342854633302</id><published>2026-07-25T11:21:19.545+05:30</published><updated>2026-07-25T11:21:19.545+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Native"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="Grafana"/><category scheme="http://www.blogger.com/atom/ns#" term="Helm"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes Logging"/><category scheme="http://www.blogger.com/atom/ns#" term="Loki"/><category scheme="http://www.blogger.com/atom/ns#" term="Observability"/><category scheme="http://www.blogger.com/atom/ns#" term="Production Debugging"/><category scheme="http://www.blogger.com/atom/ns#" term="Promtail"/><title type='text'>How We Set Up Centralized Logging in Kubernetes with Grafana Loki</title><content type='html'>&lt;p&gt;As Kubernetes environments grow, troubleshooting applications becomes increasingly difficult if we rely only on &lt;code inline=&quot;&quot;&gt;kubectl logs&lt;/code&gt;. While the command works well for individual pods, it becomes inefficient when applications are distributed across multiple namespaces, deployments and worker nodes.&lt;/p&gt;&lt;p&gt;In a production environment, pods are constantly being created, restarted and terminated. Once a pod is deleted, its logs are often lost unless they have been collected and stored somewhere centrally.&lt;/p&gt;&lt;p&gt;This is where a centralized logging solution becomes essential.&lt;/p&gt;&lt;p&gt;In this article, we will set up centralized logging in Kubernetes using Grafana, Loki and Promtail. We will also look at some of the common issues that teams encounter during installation and how to resolve them.&lt;/p&gt;&lt;h2&gt;Why Do We Need Centralized Logging?&lt;/h2&gt;&lt;p&gt;For a small cluster with only a few applications, checking logs using &lt;code inline=&quot;&quot;&gt;kubectl logs&lt;/code&gt; may be sufficient.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;However, as more applications are deployed, finding logs quickly becomes difficult.&lt;/p&gt;&lt;p&gt;Some common challenges include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Pods restart frequently.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Multiple replicas generate separate logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Applications run across different namespaces.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Logs disappear when pods are recreated.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Searching across multiple applications becomes time consuming.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A centralized logging solution solves these problems by collecting logs from every node and storing them in one place.&lt;/p&gt;&lt;h2&gt;Why Grafana, Loki and Promtail?&lt;/h2&gt;&lt;p&gt;There are several logging solutions available for Kubernetes, including the ELK Stack.&lt;/p&gt;&lt;p&gt;For our Kubernetes environments, we chose Grafana Loki because it is lightweight, easy to deploy and integrates seamlessly with Grafana.&lt;/p&gt;&lt;p&gt;The architecture is simple.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Application Pods
        │
        ▼
Promtail (DaemonSet)
        │
        ▼
      Loki
        │
        ▼
     Grafana
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each component has a specific responsibility.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Promtail collects logs from every Kubernetes node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Loki stores the logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Grafana provides a user interface to search and visualize them.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;Prerequisites&lt;/h2&gt;&lt;p&gt;Before starting the installation, make sure the following requirements are met.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Kubernetes cluster is running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Helm is installed.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;StorageClass is available.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;You have cluster administrator access.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;A namespace exists for monitoring.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Create the namespace if it doesn&#39;t already exist.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl create namespace monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;h2&gt;Step 1: Add the Grafana Helm Repository&lt;/h2&gt;&lt;p&gt;First, add the official Helm repository.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;helm repo add grafana https://grafana.github.io/helm-charts

helm repo update
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This downloads the latest Helm charts for Grafana, Loki and Promtail.&lt;/p&gt;&lt;h2&gt;Step 2: Install Loki Stack&lt;/h2&gt;&lt;p&gt;Install the Loki Stack using Helm.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;helm install loki grafana/loki-stack \
--namespace monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Depending on the chart version, Helm deploys components such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Loki&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Promtail&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Grafana (optional)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Service Accounts&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;ConfigMaps&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Wait for the installation to complete before moving to the next step.&lt;/p&gt;&lt;h2&gt;Step 3: Verify the Installation&lt;/h2&gt;&lt;p&gt;Check whether all pods are running successfully.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pods -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;A healthy deployment should look similar to this.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;NAME                                   READY   STATUS
loki-0                                 1/1     Running
promtail-xxxxx                         1/1     Running
grafana-xxxxxxxx                       1/1     Running
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If any pod is stuck in Pending or CrashLoopBackOff, investigate the issue before proceeding.&lt;/p&gt;&lt;h2&gt;Step 4: Access Grafana&lt;/h2&gt;&lt;p&gt;If an Ingress has not been configured yet, use port forwarding.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl port-forward svc/grafana 3000:80 -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Open the browser.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Log in using the administrator credentials.&lt;/p&gt;&lt;p&gt;After logging in, navigate to:&lt;/p&gt;&lt;p&gt;Connections → Data Sources&lt;/p&gt;&lt;p&gt;Verify that Loki is configured as a data source.&lt;/p&gt;&lt;h2&gt;Step 5: Verify Loki Connectivity&lt;/h2&gt;&lt;p&gt;Before exploring logs, make sure Grafana can communicate with Loki.&lt;/p&gt;&lt;p&gt;Open the Loki data source and click &quot;Save &amp;amp; Test&quot;.&lt;/p&gt;&lt;p&gt;If everything is configured correctly, Grafana displays a success message.&lt;/p&gt;&lt;p&gt;If the connection fails, verify:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Loki service name&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Namespace&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Service port&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;DNS resolution&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Network policies&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Most connectivity issues are caused by an incorrect service URL.&lt;/p&gt;&lt;h2&gt;Step 6: Explore Logs&lt;/h2&gt;&lt;p&gt;Open the Explore page in Grafana.&lt;/p&gt;&lt;p&gt;Select the Loki data source.&lt;/p&gt;&lt;p&gt;Run a simple LogQL query.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;default&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This displays logs for all pods in the default namespace.&lt;/p&gt;&lt;p&gt;To filter logs for a specific application:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{app=&quot;payment-api&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Search for error messages.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;production&quot;} |= &quot;ERROR&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also filter by container name.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{container=&quot;nginx&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;LogQL makes searching Kubernetes logs much easier compared to manually checking individual pods.&lt;/p&gt;&lt;h2&gt;Common Issues During Installation&lt;/h2&gt;&lt;p&gt;Although the installation process is straightforward, there are a few issues that commonly appear in production environments.&lt;/p&gt;&lt;h3&gt;Grafana Cannot Connect to Loki&lt;/h3&gt;&lt;p&gt;One issue we encountered was Grafana failing to connect to Loki even though both pods were running.&lt;/p&gt;&lt;p&gt;The first thing to verify is the Loki service.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get svc -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Confirm that the service name matches the URL configured in the Grafana data source.&lt;/p&gt;&lt;p&gt;Also verify that both services exist in the same namespace.&lt;/p&gt;&lt;p&gt;Most connectivity problems are caused by an incorrect service URL or namespace mismatch.&lt;/p&gt;&lt;h2&gt;Promtail Pods Remain Pending&lt;/h2&gt;&lt;p&gt;Promtail usually runs as a DaemonSet and schedules one pod on every worker node.&lt;/p&gt;&lt;p&gt;If Promtail remains in the Pending state, check the pod description.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;promtail-pod&amp;gt; -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Common reasons include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Insufficient memory&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Taints&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Node selectors&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing tolerations&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In our environment, Promtail couldn&#39;t be scheduled because the worker node didn&#39;t have enough available memory.&lt;/p&gt;&lt;p&gt;Increasing node capacity resolved the issue.&lt;/p&gt;&lt;h2&gt;Loki Pod Keeps Restarting&lt;/h2&gt;&lt;p&gt;If Loki repeatedly restarts, inspect the logs.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;loki-pod&amp;gt; -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Typical causes include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Storage permission issues&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Persistent Volume problems&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Invalid Helm configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing storage class&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Checking the logs usually identifies the problem quickly.&lt;/p&gt;&lt;h2&gt;No Logs Are Appearing&lt;/h2&gt;&lt;p&gt;Sometimes every pod appears healthy, but Grafana still doesn&#39;t display any logs.&lt;/p&gt;&lt;p&gt;Check whether Promtail is collecting logs.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;promtail-pod&amp;gt; -n monitoring
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Also verify:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Promtail is running on every node.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The correct namespace is selected.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Labels match the LogQL query.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Loki is receiving log entries.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Most &quot;missing logs&quot; issues are related to label mismatches rather than Loki itself.&lt;/p&gt;&lt;h2&gt;Useful LogQL Queries&lt;/h2&gt;&lt;p&gt;Display logs from a namespace.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;default&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Display logs for a deployment.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{app=&quot;payment-api&quot;}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Show only error messages.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;production&quot;} |= &quot;ERROR&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Show warning messages.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;production&quot;} |= &quot;WARN&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Search for a specific exception.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;{namespace=&quot;production&quot;} |= &quot;NullPointerException&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These simple queries make troubleshooting much faster than manually checking logs from individual pods.&lt;/p&gt;&lt;h2&gt;Best Practices&lt;/h2&gt;&lt;p&gt;After deploying centralized logging, consider the following recommendations.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Configure persistent storage for Loki.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Set appropriate retention policies.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure CPU and memory requests.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure resource limits.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Label workloads consistently.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Secure Grafana with authentication.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Create dashboards for frequently used queries.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure alerts for critical application errors.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Following these practices keeps the logging platform reliable as the Kubernetes cluster grows.&lt;/p&gt;&lt;p&gt;Centralized logging is one of the first observability tools every Kubernetes environment should have. While &lt;code inline=&quot;&quot;&gt;kubectl logs&lt;/code&gt; is useful for quick debugging, it becomes increasingly difficult to troubleshoot distributed applications as the number of services grows.&lt;/p&gt;&lt;p&gt;Grafana, Loki and Promtail provide a lightweight and scalable logging solution that integrates naturally with Kubernetes. Once the platform is configured, developers can search logs across namespaces, deployments and containers from a single interface, making production troubleshooting much faster.&lt;/p&gt;&lt;p&gt;In our experience, most installation issues are related to configuration rather than the tools themselves. Taking a few extra minutes to verify connectivity, resource allocation and service configuration during setup saves a significant amount of troubleshooting later.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/2101354342854633302/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/07/how-we-set-up-centralized-logging-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/2101354342854633302'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/2101354342854633302'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/07/how-we-set-up-centralized-logging-in.html' title='How We Set Up Centralized Logging in Kubernetes with Grafana Loki'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-4847313806355098821</id><published>2026-07-25T11:06:41.973+05:30</published><updated>2026-07-25T11:06:41.974+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Native"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="Exit Code 137"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes Resources"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes Troubleshooting"/><category scheme="http://www.blogger.com/atom/ns#" term="Memory Management"/><category scheme="http://www.blogger.com/atom/ns#" term="OOMKilled"/><category scheme="http://www.blogger.com/atom/ns#" term="Production Debugging"/><title type='text'>OOMKilled in Kubernetes: Understanding Exit Code 137 and How to Fix It</title><content type='html'>&lt;p&gt;If you&#39;ve worked with Kubernetes for some time, you&#39;ve probably come across a pod that suddenly restarts with the reason &lt;code inline=&quot;&quot;&gt;OOMKilled&lt;/code&gt; and an exit code of &lt;code inline=&quot;&quot;&gt;137&lt;/code&gt;. It usually happens without much warning. One moment the application is running normally, and the next moment Kubernetes terminates the container and starts a new one.&lt;/p&gt;&lt;p&gt;The first reaction is often to increase the memory limit and redeploy the application. Sometimes that works, but in many cases the same issue returns after a few hours or days because the actual problem was never investigated.&lt;/p&gt;&lt;p&gt;In most production environments, OOMKilled isn&#39;t the real problem. It&#39;s an indication that the application consumed more memory than it was allowed to use. Our objective shouldn&#39;t be to simply allocate more memory. Instead, we should understand why the application exceeded its limit in the first place.&lt;/p&gt;&lt;p&gt;In this article, we will understand what OOMKilled means, why Kubernetes reports Exit Code 137, how to investigate memory-related issues and the best practices to prevent them from happening again.&lt;/p&gt;&lt;h2&gt;What Does OOMKilled Mean?&lt;/h2&gt;&lt;p&gt;OOM stands for Out Of Memory.&lt;/p&gt;&lt;p&gt;Every container running in Kubernetes has resource limits that define the maximum amount of memory it can consume. If the application crosses that limit, the Linux kernel immediately terminates the process to protect the node from running out of memory.&lt;/p&gt;&lt;p&gt;Kubernetes detects that the container has stopped unexpectedly and restarts it according to the pod&#39;s restart policy.&lt;/p&gt;&lt;p&gt;If the application continues exceeding the memory limit after every restart, the pod may eventually enter a CrashLoopBackOff state.&lt;/p&gt;&lt;p&gt;Understanding this behaviour is important because Kubernetes isn&#39;t killing the application. The operating system is. Kubernetes simply reports what happened and starts a new container.&lt;/p&gt;&lt;h2&gt;Understanding Exit Code 137&lt;/h2&gt;&lt;p&gt;When a Linux process exits, it returns an exit code.&lt;/p&gt;&lt;p&gt;For an OOMKilled container, Kubernetes usually reports something similar to the following:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Last State:
  Terminated

Reason:
  OOMKilled

Exit Code:
  137
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Exit Code 137 indicates that the process was terminated using the SIGKILL signal.&lt;/p&gt;&lt;p&gt;In Kubernetes, this almost always means one of the following:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The application exceeded its configured memory limit.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;The Linux Out Of Memory Killer terminated the process.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes restarted the container after it exited.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Whenever we see Exit Code 137, memory usage should be the first thing we investigate.&lt;/p&gt;&lt;h2&gt;Confirm That the Pod Was OOMKilled&lt;/h2&gt;&lt;p&gt;The easiest way to verify the reason is by describing the pod.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Look for the Last State section.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Last State:
  Terminated

Reason:
  OOMKilled

Exit Code:
  137
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If both the reason and exit code match the output above, we&#39;ve confirmed that memory exhaustion caused the container to terminate.&lt;/p&gt;&lt;p&gt;Before making any configuration changes, we should understand why it happened.&lt;/p&gt;&lt;h2&gt;Review the Resource Configuration&lt;/h2&gt;&lt;p&gt;The next step is checking the memory requests and limits configured for the container.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pod &amp;lt;pod-name&amp;gt; -o yaml
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Locate the resources section.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;resources:
  requests:
    memory: &quot;512Mi&quot;
    cpu: &quot;250m&quot;

  limits:
    memory: &quot;1Gi&quot;
    cpu: &quot;500m&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;There is often confusion between requests and limits.&lt;/p&gt;&lt;p&gt;A memory request determines the amount of memory Kubernetes reserves for the container during scheduling.&lt;/p&gt;&lt;p&gt;A memory limit defines the maximum memory the application is allowed to consume.&lt;/p&gt;&lt;p&gt;Once the application crosses that limit, the Linux kernel terminates the process immediately.&lt;/p&gt;&lt;p&gt;Setting memory limits too low is one of the most common reasons for OOMKilled pods.&lt;/p&gt;&lt;h2&gt;Check Current Memory Usage&lt;/h2&gt;&lt;p&gt;Before increasing memory limits, we should understand how much memory the application is actually consuming.&lt;/p&gt;&lt;p&gt;If Metrics Server is installed, run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl top pod
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;or&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl top pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;NAME              CPU(cores)   MEMORY(bytes)
payment-api       210m         985Mi
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the container has a memory limit of 1Gi and is already consuming around 985Mi, even a small increase in workload may cause the application to exceed its limit.&lt;/p&gt;&lt;p&gt;Monitoring memory usage gives us a much clearer picture than simply guessing.&lt;/p&gt;&lt;h2&gt;Check the Previous Logs&lt;/h2&gt;&lt;p&gt;When Kubernetes restarts a container, the current logs may only contain startup information.&lt;/p&gt;&lt;p&gt;The actual problem usually exists in the previous container.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt; --previous
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Depending on the application, we may find messages related to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Memory allocation failures&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Large file uploads&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Garbage collection warnings&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Cache growth&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Unexpected spikes in workload&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Checking the previous logs has helped us identify the root cause of many production incidents.&lt;/p&gt;&lt;h2&gt;Common Reasons for OOMKilled&lt;/h2&gt;&lt;p&gt;Although every application behaves differently, most OOMKilled incidents fall into a few common categories.&lt;/p&gt;&lt;h3&gt;Memory Leaks&lt;/h3&gt;&lt;p&gt;Applications that continuously allocate memory without releasing it eventually consume all available memory.&lt;/p&gt;&lt;p&gt;Initially everything appears normal.&lt;/p&gt;&lt;p&gt;After running for several hours or days, memory usage gradually increases until the container reaches its configured limit.&lt;/p&gt;&lt;p&gt;Monitoring memory growth over time usually helps identify this pattern.&lt;/p&gt;&lt;h3&gt;Processing Large Files&lt;/h3&gt;&lt;p&gt;Applications processing PDFs, images, videos or large Excel files often require much more memory than expected.&lt;/p&gt;&lt;p&gt;If the entire file is loaded into memory, temporary spikes can exceed the configured limit.&lt;/p&gt;&lt;p&gt;Whenever possible, processing files in smaller chunks significantly reduces memory consumption.&lt;/p&gt;&lt;h3&gt;Loading Large Datasets&lt;/h3&gt;&lt;p&gt;Another common mistake is loading an entire dataset into memory before processing it.&lt;/p&gt;&lt;p&gt;Instead of loading thousands of records at once, processing them in batches or using streaming techniques keeps memory usage under control.&lt;/p&gt;&lt;h3&gt;Traffic Spikes&lt;/h3&gt;&lt;p&gt;Applications that perform well under normal traffic may consume considerably more memory during peak usage.&lt;/p&gt;&lt;p&gt;Higher request volumes often result in additional objects being created, more active database connections and larger caches.&lt;/p&gt;&lt;p&gt;Without sufficient memory planning, the container eventually exceeds its limit.&lt;/p&gt;&lt;h3&gt;Incorrect Resource Configuration&lt;/h3&gt;&lt;p&gt;Sometimes the application itself isn&#39;t the problem.&lt;/p&gt;&lt;p&gt;The configured memory limit simply doesn&#39;t reflect the application&#39;s actual workload.&lt;/p&gt;&lt;p&gt;Development and testing environments often use much smaller datasets than production, making it difficult to estimate realistic memory requirements.&lt;/p&gt;&lt;h2&gt;Should We Simply Increase the Memory Limit?&lt;/h2&gt;&lt;p&gt;Increasing the memory limit may stop the restarts temporarily, but it shouldn&#39;t be the first solution.&lt;/p&gt;&lt;p&gt;Before changing resource limits, it&#39;s worth asking a few questions.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Did the issue start after a recent deployment?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Has application traffic increased?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Are larger files being processed?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Has a new feature introduced additional memory usage?&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Is memory usage continuously increasing over time?&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Answering these questions often leads us to the actual root cause instead of masking the problem.&lt;/p&gt;&lt;h2&gt;Review Recent Deployments&lt;/h2&gt;&lt;p&gt;If the application was working correctly yesterday but started failing after a deployment, compare the recent changes.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout history deployment &amp;lt;deployment-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Recent code changes may have introduced:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Larger in-memory caches&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Additional background workers&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;New libraries&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Bigger response payloads&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Changes in data processing&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If production is impacted, rolling back to the previous deployment can restore service while the investigation continues.&lt;/p&gt;&lt;h2&gt;Best Practices to Prevent OOMKilled&lt;/h2&gt;&lt;p&gt;Preventing memory issues is much easier than troubleshooting them during an outage.&lt;/p&gt;&lt;p&gt;Some practices that have worked well across production environments include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Configure realistic memory requests and limits.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Continuously monitor CPU and memory usage.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Process large files in batches.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Stream large datasets whenever possible.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Optimise application caching.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Load test applications before production releases.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Review memory consumption after every major deployment.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Configure Horizontal Pod Autoscaler where appropriate.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Small improvements in memory management often make a significant difference to application stability.&lt;/p&gt;&lt;h2&gt;Common Mistakes&lt;/h2&gt;&lt;p&gt;These are some of the mistakes we see most frequently while investigating OOMKilled incidents.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Increasing memory limits without identifying the root cause.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ignoring historical memory usage.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Deploying applications without load testing.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Assuming Kubernetes is responsible for application crashes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Forgetting to review previous container logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Using the same resource configuration for every environment.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Avoiding these mistakes usually makes troubleshooting much faster.&lt;/p&gt;&lt;p&gt;OOMKilled is one of the most common Kubernetes issues, but it&#39;s also one of the easiest to diagnose once we understand what Exit Code 137 represents.&lt;/p&gt;&lt;p&gt;Rather than treating OOMKilled as the actual problem, we should treat it as an indication that the application consumed more memory than its configured limit.&lt;/p&gt;&lt;p&gt;A structured troubleshooting process always produces better results than making configuration changes based on assumptions. Confirm the reason using &lt;code inline=&quot;&quot;&gt;kubectl describe&lt;/code&gt;, review the configured resource limits, analyse memory usage, inspect the previous logs and compare recent deployments before increasing memory.&lt;/p&gt;&lt;p&gt;In many cases, Kubernetes has already provided everything we need to identify the root cause. We simply need to collect the information in the right order and let the evidence guide our investigation.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/4847313806355098821/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/07/oomkilled-in-kubernetes-understanding.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4847313806355098821'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4847313806355098821'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/07/oomkilled-in-kubernetes-understanding.html' title='OOMKilled in Kubernetes: Understanding Exit Code 137 and How to Fix It'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-4274549910403926393</id><published>2026-07-25T10:58:54.523+05:30</published><updated>2026-07-25T10:58:54.523+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Cloud Native"/><category scheme="http://www.blogger.com/atom/ns#" term="Containers"/><category scheme="http://www.blogger.com/atom/ns#" term="CrashLoopBackOff"/><category scheme="http://www.blogger.com/atom/ns#" term="devops"/><category scheme="http://www.blogger.com/atom/ns#" term="DevOps Tutorial"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="Kubernetes Debugging"/><category scheme="http://www.blogger.com/atom/ns#" term="Troubleshooting"/><title type='text'>Why Your Kubernetes Pod Keeps Restarting: A Complete Debugging Guide</title><content type='html'>&lt;p&gt;If you&#39;ve been working with Kubernetes for any length of time, you&#39;ve probably encountered a pod that refuses to stay running. One moment it&#39;s starting successfully, and the next moment it&#39;s restarting. After a few attempts, Kubernetes reports a &lt;code inline=&quot;&quot;&gt;CrashLoopBackOff&lt;/code&gt; status, leaving many engineers wondering what went wrong.&lt;/p&gt;&lt;p&gt;The first reaction is often to delete the pod and hope Kubernetes creates a healthy replacement. While this may appear to solve the problem temporarily, it rarely fixes the actual issue. More importantly, deleting the pod too quickly can remove valuable information that would have helped identify the root cause.&lt;/p&gt;&lt;p&gt;The good news is that Kubernetes almost always tells us why a pod is restarting. We simply need to know where to look and follow a structured troubleshooting approach instead of making assumptions.&lt;/p&gt;&lt;p&gt;In this article, we will walk through the exact process we can use to diagnose and resolve Kubernetes pods that keep restarting.&lt;/p&gt;&lt;h2&gt;Step 1: Check the Pod Status&lt;/h2&gt;&lt;p&gt;Whenever a pod starts restarting, our first objective is to understand what Kubernetes already knows about it.&lt;/p&gt;&lt;p&gt;The first command we should run is:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get pods
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Example output:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;NAME                    READY   STATUS             RESTARTS   AGE
payment-api-65d8fd      0/1     CrashLoopBackOff   12         18m
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pay close attention to these three columns:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;STATUS&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;RESTARTS&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;AGE&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;A restart count of 10 or 20 immediately tells us the application has been crashing repeatedly and Kubernetes has been trying to recover it.&lt;/p&gt;&lt;p&gt;Some common pod statuses include:&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Status&lt;/th&gt;&lt;th&gt;Meaning&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Running&lt;/td&gt;&lt;td&gt;Application is healthy&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pending&lt;/td&gt;&lt;td&gt;Waiting to be scheduled&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CrashLoopBackOff&lt;/td&gt;&lt;td&gt;Container keeps crashing after startup&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ImagePullBackOff&lt;/td&gt;&lt;td&gt;Unable to pull the container image&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ErrImagePull&lt;/td&gt;&lt;td&gt;Image download failed&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Completed&lt;/td&gt;&lt;td&gt;Job completed successfully&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Terminating&lt;/td&gt;&lt;td&gt;Pod is shutting down&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;p&gt;Once we&#39;ve confirmed the pod is restarting, the next step is to gather more information.&lt;/p&gt;&lt;h2&gt;Step 2: Describe the Pod&lt;/h2&gt;&lt;p&gt;One of the most useful commands in Kubernetes troubleshooting is:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Many engineers immediately jump to application logs, but &lt;code inline=&quot;&quot;&gt;kubectl describe&lt;/code&gt; provides far more context.&lt;/p&gt;&lt;p&gt;It includes information such as:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Current container state&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Previous container state&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Restart count&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Mounted volumes&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Environment variables&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Probe failures&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Scheduling information&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Events&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The &lt;strong&gt;Events&lt;/strong&gt; section at the bottom deserves special attention because Kubernetes records everything significant that happened to the pod.&lt;/p&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Warning  Unhealthy
Readiness probe failed

Warning  BackOff
Back-off restarting failed container
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In many situations, the Events section already points us in the right direction before we even inspect the application logs.&lt;/p&gt;&lt;h2&gt;Step 3: Read the Application Logs&lt;/h2&gt;&lt;p&gt;Once we&#39;ve reviewed the pod details, it&#39;s time to inspect the application logs.&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the pod has already restarted, don&#39;t forget to check the logs from the previous container instance:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl logs &amp;lt;pod-name&amp;gt; --previous
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This is one of the most overlooked commands in Kubernetes.&lt;/p&gt;&lt;p&gt;When a container crashes and restarts, the current logs may only show startup messages. The actual exception often exists only in the previous container&#39;s logs. We&#39;ve solved many production issues simply by checking &lt;code inline=&quot;&quot;&gt;kubectl logs --previous&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;Now that we&#39;ve gathered the basic information, we can start identifying the actual reason behind the restarts.&lt;/p&gt;&lt;h2&gt;Common Causes of Restarting Pods&lt;/h2&gt;&lt;p&gt;In most production environments, restarting pods usually fall into one of the following categories.&lt;/p&gt;&lt;h3&gt;CrashLoopBackOff&lt;/h3&gt;&lt;p&gt;This is probably the most common Kubernetes error.&lt;/p&gt;&lt;p&gt;A &lt;code inline=&quot;&quot;&gt;CrashLoopBackOff&lt;/code&gt; doesn&#39;t tell us what failed—it simply tells us Kubernetes keeps restarting the container because it exits shortly after starting.&lt;/p&gt;&lt;p&gt;Common reasons include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Application exceptions&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing environment variables&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Database connection failures&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Invalid configuration&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing ConfigMaps&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing Secrets&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Startup script failures&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Error: Database connection refused
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The application exits.&lt;/p&gt;&lt;p&gt;Kubernetes restarts it.&lt;/p&gt;&lt;p&gt;The application crashes again.&lt;/p&gt;&lt;p&gt;Eventually Kubernetes delays each restart attempt and reports &lt;code inline=&quot;&quot;&gt;CrashLoopBackOff&lt;/code&gt;.&lt;/p&gt;&lt;p&gt;It&#39;s important to remember that &lt;strong&gt;CrashLoopBackOff is a symptom, not the root cause.&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;The real reason is almost always available in the application logs.&lt;/p&gt;&lt;h2&gt;OOMKilled&lt;/h2&gt;&lt;p&gt;Another common reason for pod restarts is an out-of-memory condition.&lt;/p&gt;&lt;p&gt;If the application consumes more memory than allowed, the Linux kernel terminates the container.&lt;/p&gt;&lt;p&gt;We can verify this using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Look for something similar to:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-text&quot;&gt;Last State:
Terminated

Reason:
OOMKilled
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Typical causes include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Memory leaks&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Processing large files&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Image or PDF conversion&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Loading large datasets into memory&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Incorrect resource limits&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Many teams immediately increase the memory limit and redeploy the application.&lt;/p&gt;&lt;p&gt;While that may stop the restarts temporarily, it&#39;s always worth understanding why the application is consuming excessive memory before increasing resources.&lt;/p&gt;&lt;h2&gt;Readiness Probe Failures&lt;/h2&gt;&lt;p&gt;A readiness probe tells Kubernetes whether the application is ready to receive traffic.&lt;/p&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;readinessProbe:
  httpGet:
    path: /health
    port: 8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the readiness probe fails:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;The pod continues running.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Kubernetes stops routing traffic to it.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Common reasons include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Wrong endpoint&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Wrong port&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Slow application startup&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Database not yet available&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Dependent services still starting&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Readiness failures usually indicate that the application isn&#39;t fully initialised yet.&lt;/p&gt;&lt;h2&gt;Liveness Probe Failures&lt;/h2&gt;&lt;p&gt;Unlike readiness probes, liveness probes determine whether the application is still healthy.&lt;/p&gt;&lt;p&gt;If a liveness probe keeps failing, Kubernetes assumes the application is unhealthy and restarts it automatically.&lt;/p&gt;&lt;p&gt;Example:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;livenessProbe:
  httpGet:
    path: /health
    port: 8080
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One common mistake is configuring the liveness probe too aggressively.&lt;/p&gt;&lt;p&gt;For example, if an application requires 60 seconds to initialise but the liveness probe starts after only 15 seconds, Kubernetes may repeatedly kill the container before it has a chance to finish starting.&lt;/p&gt;&lt;h2&gt;ImagePullBackOff&lt;/h2&gt;&lt;p&gt;Sometimes the container never starts because Kubernetes cannot download the container image.&lt;/p&gt;&lt;p&gt;Possible reasons include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Incorrect image name&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Wrong image tag&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Private registry authentication failure&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Registry connectivity issues&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Image does not exist&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;The quickest way to investigate is:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl describe pod &amp;lt;pod-name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Again, the Events section usually contains the exact reason for the image pull failure.&lt;/p&gt;&lt;h2&gt;Configuration Problems&lt;/h2&gt;&lt;p&gt;Configuration errors are another common cause of restarting pods.&lt;/p&gt;&lt;p&gt;Examples include:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Missing ConfigMaps&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing Secrets&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Incorrect environment variables&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Invalid file paths&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Missing certificates&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Invalid application configuration&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Even a simple typo in an environment variable can prevent an application from starting successfully.&lt;/p&gt;&lt;h2&gt;Step 4: Check Resource Usage&lt;/h2&gt;&lt;p&gt;Sometimes the problem isn&#39;t the application itself.&lt;/p&gt;&lt;p&gt;The Kubernetes node may be under heavy resource pressure.&lt;/p&gt;&lt;p&gt;We can check resource usage using:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl top pod

kubectl top node
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These commands help identify:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;High CPU usage&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;High memory usage&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Resource spikes&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Node pressure&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;If these commands don&#39;t work, ensure the Kubernetes Metrics Server is installed.&lt;/p&gt;&lt;h2&gt;Step 5: Review Cluster Events&lt;/h2&gt;&lt;p&gt;Cluster events often provide additional context that application logs cannot.&lt;/p&gt;&lt;p&gt;Run:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl get events --sort-by=.metadata.creationTimestamp
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Look for messages related to:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Failed scheduling&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Failed mounts&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Failed image pulls&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Probe failures&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Resource exhaustion&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Events frequently tell the complete story of what happened before the pod entered its restart cycle.&lt;/p&gt;&lt;h2&gt;Step 6: Review Recent Deployments&lt;/h2&gt;&lt;p&gt;If the application was working yesterday but started restarting after a deployment, don&#39;t ignore the possibility that the latest release introduced the issue.&lt;/p&gt;&lt;p&gt;Review the deployment history:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout history deployment payment-api
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If required, roll back to the previous version:&lt;/p&gt;&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;kubectl rollout undo deployment payment-api
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Rolling back isn&#39;t the final solution, but it can restore service quickly while we continue investigating the root cause.&lt;/p&gt;&lt;h2&gt;A Simple Troubleshooting Checklist&lt;/h2&gt;&lt;p&gt;Whenever we encounter a restarting pod, following a consistent process saves time and avoids unnecessary guesswork.&lt;/p&gt;&lt;ol&gt;&lt;li&gt;&lt;p&gt;Check the pod status.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Describe the pod.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Review the current logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Review the previous logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Check the Events section.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Verify CPU and memory usage.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Inspect readiness and liveness probes.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Check for image pull errors.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Review recent deployments.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;Following the same sequence every time helps us diagnose problems much faster.&lt;/p&gt;&lt;h2&gt;Common Mistakes&lt;/h2&gt;&lt;p&gt;Over the years, we&#39;ve seen the same mistakes repeated in many Kubernetes environments.&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Deleting the pod before collecting logs.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Ignoring the Events section.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Increasing memory without understanding the root cause.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Restarting deployments repeatedly instead of investigating.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Forgetting to use &lt;code inline=&quot;&quot;&gt;kubectl logs --previous&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Assuming Kubernetes is the problem when the application itself is crashing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Avoiding these mistakes can significantly reduce troubleshooting time.&lt;/p&gt;&lt;p&gt;Kubernetes doesn&#39;t restart containers without a reason. Every restart is a symptom of an underlying issue, whether it&#39;s an application crash, resource exhaustion, configuration error, failed health check or infrastructure problem.&lt;/p&gt;&lt;p&gt;The goal isn&#39;t to memorise dozens of Kubernetes commands. Instead, we should develop a structured troubleshooting approach that helps us identify the root cause quickly and consistently.&lt;/p&gt;&lt;p&gt;The next time you see a pod stuck in &lt;code inline=&quot;&quot;&gt;CrashLoopBackOff&lt;/code&gt;, resist the temptation to delete it immediately. Start by checking the pod status, describing the pod, reviewing the logs and inspecting the Events section. In most cases, Kubernetes has already provided enough information to lead us to the solution.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/4274549910403926393/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2026/07/why-your-kubernetes-pod-keeps.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4274549910403926393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4274549910403926393'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2026/07/why-your-kubernetes-pod-keeps.html' title='Why Your Kubernetes Pod Keeps Restarting: A Complete Debugging Guide'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-5120016747187113441</id><published>2022-10-02T16:45:00.003+05:30</published><updated>2022-10-02T16:45:35.772+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Express"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="NodeJs"/><category scheme="http://www.blogger.com/atom/ns#" term="XML"/><title type='text'>NodeJs Read XML file and Parse Data</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;Few days back I worked on task to read XML file in NodeJs and parse the data and convert data to the JSON format. Here in this blog I am going explain how I did achieved this.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Following is our sample XML file.&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;lt;root&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;lt;parent&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;firstchild&amp;gt;First Child Content 1&amp;lt;/firstchild&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;secondchild&amp;gt;Second Child Content 1&amp;lt;/secondchild&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/parent&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;lt;parent&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;firstchild&amp;gt;First Child Content 2&amp;lt;/firstchild&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;secondchild&amp;gt;Second Child Content 2&amp;lt;/secondchild&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/parent&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;lt;/root&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;b&gt;Step 1 : Install necessary NPM packages&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;First install following packages in your NodeJs application.&lt;/p&gt;&lt;p&gt;npm install --save&amp;nbsp;xmldom&lt;/p&gt;&lt;p&gt;mpm install --save&amp;nbsp;hashmap&lt;/p&gt;&lt;p&gt;Here xmldom is the package we are going to use to parse the XML data and hasmap package we are going to use to convert and save data in JSON format.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;b&gt;Step 2 : Import necessary packages in script&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: large;&quot;&gt;const { readFile } = require(&#39;fs/promises&#39;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;const xmldom = require(&#39;xmldom&#39;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;const HashMap = require(&#39;hashmap&#39;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: large;&quot;&gt;We are going to use readFile from fs/promises. Also we will use xmldom to parse the string data. xmldom is a&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;b&gt;A JavaScript implementation of W3C DOM for Node.js, Rhino and the browser. Fully compatible with W3C DOM level2; and some compatible with level3. Supports DOMParser and XMLSerializer interface such as in browser.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;font-size: large;&quot;&gt;Step 3 : Read the XML file&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;const readXMLFile = async()=&amp;gt; {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;var parser = new xmldom.DOMParser();&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const result = await readFile(&#39;./data.xml&#39;,&quot;utf8&quot;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const dom = parser.parseFromString(result, &#39;text/xml&#39;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;}&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Here we are using async function to read the XML file as we want to wait till XML file is completely finished. Also we created a&amp;nbsp;&lt;span style=&quot;font-size: large;&quot;&gt;xmldom.DOMParser which we will use to parse the string data of the file. This parser will give you all the TAGs of the XML file just like we access standard HTML tags. With this we can use&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;getElementsByTagName to get XML tags.&amp;nbsp;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b style=&quot;font-size: large;&quot;&gt;Step 4 : Convert XML data to hasmap&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;const readXMLFile = async()=&amp;gt; {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;var parser = new xmldom.DOMParser();&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;const dataMap = new HashMap();&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const result = await readFile(&#39;./data.xml&#39;,&quot;utf8&quot;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; const dom = parser.parseFromString(result, &#39;text/xml&#39;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;var parentList = dom.getElementsByTagName(&quot;&lt;/span&gt;parent&lt;span style=&quot;font-size: medium;&quot;&gt;&quot;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;for(var i =0; i &amp;lt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parentList&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;.length; i++) {&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;const parent =&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parentList&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;[i];&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;const firstchild =&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;.getElementsByTagName(&quot;&lt;/span&gt;firstchild&lt;span style=&quot;font-size: medium;&quot;&gt;&quot;)[0].textContent;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;const secondchild =&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parent&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;.getElementsByTagName(&quot;&lt;/span&gt;secondchild&lt;span style=&quot;font-size: medium;&quot;&gt;&quot;)[0].textContent;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;const parentMap = new HashMap();&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parentMap&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;.set(&quot;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;firstchild&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&quot;,&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;firstchild&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parentMap&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;.set(&quot;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;secondchild&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&quot;,&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp;secondchild&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;dataMap.set(i,&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;parentMap&lt;/span&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;);&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-size: large;&quot;&gt;&amp;nbsp; &amp;nbsp; }&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;}&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;In the above function we got list of parents by&amp;nbsp;getElementsByTagName method and then we are iterating&amp;nbsp;&amp;nbsp;through it and accessing the child tags and getting it&#39;s text content. Then we are simply storing it in hasmap with unique key.&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;Hope this helps you.&lt;/span&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/5120016747187113441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2022/10/nodejs-read-xml-file-and-parse-data.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/5120016747187113441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/5120016747187113441'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2022/10/nodejs-read-xml-file-and-parse-data.html' title='NodeJs Read XML file and Parse Data'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-3525442227240468629</id><published>2022-07-03T11:25:00.001+05:30</published><updated>2022-07-05T16:08:04.178+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="NodeJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Testing"/><category scheme="http://www.blogger.com/atom/ns#" term="UnitTest"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>Mock node-fetch with JEST</title><content type='html'>&lt;p&gt;Recently I tried my hands on Jest - the popular JavaScript Testing Library. In my application we were using node-fetch to make API calls. I used Jest to mock and test this API calls. Here in this blog I will explain on how to mock node-fetch with Jest.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Following is my function to call the GET API.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;fetch_get.js&lt;/b&gt;&lt;/p&gt;&lt;p&gt;const fetch = require(&#39;node-fetch&#39;);&lt;/p&gt;&lt;p&gt;module.exports = async () =&amp;gt; {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; return await fetch(&#39;http://YOUR_GET_URL&#39;).then(res =&amp;gt; res.json());&lt;/p&gt;&lt;p&gt;};&lt;/p&gt;&lt;div&gt;Now to test this create a test file with name &lt;b&gt;test.fetch_get.js&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 1: First import the function.&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;const fetch_get = require(&#39;../fetch_get&#39;);&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 2 : Mock the node-fetch with Jest&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;const fetch = require(&#39;node-fetch&#39;);&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;jest.mock(&#39;node-fetch&#39;, ()=&amp;gt;jest.fn())&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 3: Create Mock response&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;const mockedRes = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &quot;success&quot;: true,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &quot;data&quot;: [&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; id: 1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; text: &#39;Test Data 1&#39;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; },&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; id: 1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; text: &#39;Test Data 2&#39;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;div&gt;&amp;nbsp; ]&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 4: Add Test&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;describe(&quot;Test get fetch&quot;, () =&amp;gt; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; let data;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; it(&#39;It should return the data&#39;, () =&amp;gt; {&lt;/div&gt;&lt;div&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;const response = Promise.resolve({&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ok: true,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; status: 200,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; json: () =&amp;gt; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; return mockedRes;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; fetch.mockImplementation(()=&amp;gt; response)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data = await fetch_get();&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; expect(data).toEqual(mockedRes);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; });&lt;/div&gt;&lt;div&gt;});&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In above code we have created a rest and mocked the response to return our response when we call .json() method for response. Then we are simply comparing the response. This is a very simple test. Here in stead of comparing data, you may have other tests like checking length of data or checking specific data etc.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;Step 5: Run Test&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Run the test with npm test or npm run test and you will see the following result.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;Test get fetch&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ✓ It should return the data (17 ms)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Test Suites: 1 passed, 1 total&lt;/div&gt;&lt;div&gt;Tests:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;1 passed, 1 total&lt;/div&gt;&lt;div&gt;Snapshots:&amp;nbsp; &amp;nbsp;0 total&lt;/div&gt;&lt;div&gt;Time:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.313 s, estimated 1 s&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope this helps you.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/3525442227240468629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2022/07/mock-node-fetch-with-jest.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/3525442227240468629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/3525442227240468629'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2022/07/mock-node-fetch-with-jest.html' title='Mock node-fetch with JEST'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-6346488118811494455</id><published>2022-01-29T16:32:00.001+05:30</published><updated>2022-01-29T16:33:17.256+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="container"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="kubectl"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><title type='text'>How to Execute Shell Script from Dockerfile</title><content type='html'>&lt;p&gt;Recently I faced a problem with Docker build. Before we build the image there was a requirement to cleanup something from MongoDB. For that we tried to create shell script and execute it from Dockerfile before we start the service. Here in this blog I will explain how you can execute the shell script from Dockerfile.&amp;nbsp;&lt;/p&gt;&lt;p&gt;For that first create the shell script in the same context of Dockerfile. That means the file should be in the same folder or subfolder where Dockerfile is there.&amp;nbsp;&lt;/p&gt;&lt;p&gt;We can not access file outside the Docker build context so file has to be in the same folder.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;nano test.sh&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;You can put your content in this file for the tasks you want to do with this file.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;Now first we will copy the file in docker build context. So that it can be executed. This step is mandatory or else it will not find file. Add following lines of code in your Dockerfile.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;FROM alpine3.15&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;COPY test.sh ./test.sh&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Next step we have to change access rights of the script so it can be executed.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;RUN chmod +x ./test.sh&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Now since we have file in the Docker build context and it has proper access rights we can execute the file.&amp;nbsp;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;RUN sh ./test.sh&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 21px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;That&#39;s it and now when to service starts it will execute the file and do all the actions which you have added in shell script.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Hope this helps you.&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/6346488118811494455/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2022/01/how-to-execute-shell-script-from.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6346488118811494455'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6346488118811494455'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2022/01/how-to-execute-shell-script-from.html' title='How to Execute Shell Script from Dockerfile'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-9102778756180916034</id><published>2022-01-03T21:44:00.003+05:30</published><updated>2022-01-03T21:44:29.811+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="container"/><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="kubectl"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="kublet"/><title type='text'>Kubernetes ImagePullBackOff error</title><content type='html'>&lt;p&gt;Recently I faced an issue while working&amp;nbsp;Kubernetes cluster. I was trying to build docker image from local repository to test some changes in production before we merge the code. After building the docker image and recreating the container it was showing&amp;nbsp;ImagePullBackOff error when I check the status with&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;kubectl get pods&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;In this blog I am going to mention the possible cause for this error and will explain the resolution which worked for me.&lt;/p&gt;&lt;p&gt;In a Kubernetes, there’s an agent on for node which is called kubelet. This is responsible for running containers in the nodes. For some reason if image can&#39;t be pulled the kublet will throw ImagePullBackOff error.&amp;nbsp;&lt;/p&gt;&lt;p&gt;There are some possible reasons for this when kubectl is not able to pull image from mentioned registry.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Either image or tag is not available.&amp;nbsp;&lt;/p&gt;&lt;p&gt;The name of the image or tag is wrong in deployment yaml file&lt;/p&gt;&lt;p&gt;kubectl does not have access to image registry.&amp;nbsp;&lt;/p&gt;&lt;p&gt;In my case there was no such issues mentioned above. The image with tag was there. I have specified the correct name in deployment yaml file and because it was a local registry, there was no need of authentication.&amp;nbsp;&lt;/p&gt;&lt;p&gt;So here is how I solved this issue. I set image pull policy to following value in my deployment yaml file.&lt;/p&gt;&lt;p&gt;&lt;b&gt;imagePullPolicy: IfNotPresent&lt;/b&gt;&lt;/p&gt;&lt;div&gt;The reason it worked is, the kubectl was trying to find image in registry but it was not present because it was local registry so then it tried to find image in local repository and caches it.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This solution worked for me because I was using local registry. If you are facing such issue try setting above value to imagePullPolicy and it may work. Hope this helps you.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/9102778756180916034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2022/01/kubernetes-imagepullbackoff-error.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/9102778756180916034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/9102778756180916034'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2022/01/kubernetes-imagepullbackoff-error.html' title='Kubernetes ImagePullBackOff error'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-4832817456041167415</id><published>2021-07-31T15:14:00.002+05:30</published><updated>2021-07-31T15:14:49.565+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="React"/><category scheme="http://www.blogger.com/atom/ns#" term="React Native"/><category scheme="http://www.blogger.com/atom/ns#" term="ReactJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Application"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>Wait for State Changes with Redux Saga</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;As we know Redux saga allows us to respond to actions outside Redux store. It&#39;s kind of middleware library to handle side effects with ease. This side effect could be anything like calling APIs, doing some IO operations or anything. While working with Saga sometime it happens that we also want to detect state changes and do some actions after it. In this blog I am going to explain how you can wait or detect Redux state changes with Saga.&lt;/p&gt;&lt;p&gt;Let&#39;s understand with an example. For example there is an API call to get access token and as soon as you have access toke available in state you want to call some other actions like background sync etc.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;function* waitForLoginToken(selector) {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; if (yield select(selector)) return;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; while (true) {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; yield take(&#39;*&#39;);&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; if (yield select(selector)) return;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;export function* postSignInAction(payload) {&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;cost loginTokenSelector = state =&amp;gt; state.auth.loginToken;&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;yield call(waitForLoginToken, loginTokenSelector);&lt;/p&gt;&lt;p&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;yield put({ type: &#39;BACKGROUND_SYNC&#39; });&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;function* mySaga(){&lt;/p&gt;&lt;p&gt;&amp;nbsp; yield takeEvery(&#39;SIGN_IN&#39;, postSignInAction);&lt;/p&gt;&lt;p&gt;}&lt;br /&gt;&lt;/p&gt;&lt;p&gt;As you can see in above code, we take every sign in action and call postSignInAction which will wait for state change.&lt;/p&gt;&lt;p&gt;We defined state selector as state.auth.loginToken. Till the time loginToken is not set in state.auth it will wait as we are using while loop to wait for state change. Once we get it in state we call next action.&amp;nbsp;&lt;/p&gt;&lt;p&gt;This way you can &amp;amp; detect state change with Redux Saga. Hope this helps you.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/4832817456041167415/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/07/wait-for-state-changes-with-redux-saga.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4832817456041167415'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4832817456041167415'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/07/wait-for-state-changes-with-redux-saga.html' title='Wait for State Changes with Redux Saga'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-467066595072417986</id><published>2021-07-17T16:08:00.003+05:30</published><updated>2021-07-17T16:08:25.476+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><category scheme="http://www.blogger.com/atom/ns#" term="ReactJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Application"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>React-Draft-Wysiwyg - Find Text Option</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;Recently I was working on POC for rich text editor using&amp;nbsp;&lt;a href=&quot;https://github.com/jpuri/react-draft-wysiwyg&quot; target=&quot;_blank&quot;&gt;React-Draft-Wysiwyg&lt;/a&gt; editor.&amp;nbsp;&lt;/p&gt;&lt;p&gt;There we have a requirement to add find &amp;amp; replace dialog box which should find the matching text from all the blocks and height it with background color. For the POC we added find text functionality. Here in this blog I will explain how to do it.&amp;nbsp;&lt;/p&gt;&lt;p&gt;For this I have created separate React component and add it as custom option to editor toolbar. Let&#39;s understand it step by step.&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you want to know how to add custom option you can find reference from here.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://jpuri.github.io/react-draft-wysiwyg/#/docs&quot;&gt;https://jpuri.github.io/react-draft-wysiwyg/#/docs&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;1) Create Modal with Text input and Button&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please note I have used grommet UI library to build the POC. So text input and button was imported from Grommet.&lt;/p&gt;&lt;p&gt;&amp;lt;TextInput&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; data-cy=&quot;find-text&quot;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; autoFocus&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; onChange={this.onChangeFindText}&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; value={this.state.findText}&lt;/p&gt;&lt;p&gt;/&amp;gt;&lt;/p&gt;&lt;p&gt;&amp;lt;Button&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; id=&quot;find&quot;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; label=&quot;Find&quot;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; onClick={this.onFindClick}&lt;/p&gt;&lt;p&gt;/&amp;gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;2) Handle Find Click Event&lt;/b&gt;&lt;/p&gt;&lt;p&gt;onFindClick = () =&amp;gt; {&lt;/p&gt;&lt;p&gt;&amp;nbsp; const search = this.state.findText;&lt;/p&gt;&lt;p&gt;&amp;nbsp; let contentState = convertToRaw(this.props.editorState.getCurrentContent());&lt;/p&gt;&lt;p&gt;&amp;nbsp; contentState.blocks.forEach(block =&amp;gt; {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; const text = block.text;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; const matches = [...text.matchAll(search)];&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; if(matches.length &amp;gt; 0) {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; matches.forEach(match =&amp;gt;{&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; block.inlineStyleRanges.push({length: match[0].length,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; offset: match.index,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; style: &quot;bgcolor-rgb(247,218,100)&quot;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; })&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp; });&lt;/p&gt;&lt;p&gt;&amp;nbsp; let newEditorState = {&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; editorState: EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; contentState: null&lt;/p&gt;&lt;p&gt;&amp;nbsp; }&lt;/p&gt;&lt;p&gt;&amp;nbsp; this.props.onChange(EditorState.createWithContent(convertFromRaw({blocks: contentState.blocks,entityMap: {}})));&lt;/p&gt;&lt;p&gt;}&lt;/p&gt;&lt;p&gt;In above code we are getting search text from the state and matching it with texts of all custom blocks. Where ever it matches we are setting inline styles in blocks with yellow color background. and then setting state of editor again with new blocks.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Hope this helps you.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/467066595072417986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/07/react-draft-wysiwyg-find-text-option.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/467066595072417986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/467066595072417986'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/07/react-draft-wysiwyg-find-text-option.html' title='React-Draft-Wysiwyg - Find Text Option'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-1857685877421545733</id><published>2021-07-04T15:55:00.000+05:30</published><updated>2021-07-04T15:55:21.938+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Docker"/><category scheme="http://www.blogger.com/atom/ns#" term="kubernetes"/><category scheme="http://www.blogger.com/atom/ns#" term="MongoDB"/><category scheme="http://www.blogger.com/atom/ns#" term="NodeJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>Docker MongoDB terminates when it runs out of memory</title><content type='html'>&lt;p&gt;When you have multiple services running in docker container it&#39;s quite possible that you have an issues with certain services when your docker container runs out of memory. MongoDB is one such service.&amp;nbsp;&lt;/p&gt;&lt;p&gt;On docker container when you have MongoDB running and when it starts storing huge data it starts consuming lots of memory and that&#39;s where you have an issue. MongoDB will crash after sometime where isn&#39;t much memory left.&amp;nbsp;&lt;/p&gt;&lt;p&gt;The reason behind this is the IO model of MongoDB, it tries to keep as much data as possible in cache so read and write operations are much faster. But this creates an issue with docker as we have limited memory and lots of services are sharing that.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Starting from MongoDB 3.2 on words WiredTiger storage engine is the default one for MongoDB and it&#39;s recommended.&amp;nbsp;&lt;/p&gt;&lt;p&gt;There are various advantages of WiredTiger storage engine. For example,&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Document Level Concurrency&lt;/li&gt;&lt;li&gt;Snapshots and Checkpoints&lt;/li&gt;&lt;li&gt;Journal&lt;/li&gt;&lt;li&gt;Compression&lt;/li&gt;&lt;li&gt;Memory Use&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;One of most useful feature is Memory use.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;With WiredTiger, MongoDB utilizes both the WiredTiger internal cache and the filesystem cache.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can control it with&amp;nbsp;&lt;b&gt;--wiredTigerCacheSizeGB&lt;/b&gt; configuration.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;The --wiredTigerCacheSizeGB limits the size of the WiredTiger internal cache. The operating system will use the available free memory for filesystem cache, which allows the compressed MongoDB data files to stay in memory. In addition, the operating system will use any free RAM to buffer file system blocks and file system cache.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;With this setting you can enhance memory usage. MongoDB will not use excessive memory and with heavy data usage on docker container MongoDB will not crash on excessive memory usage.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope this helps you.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/1857685877421545733/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/07/docker-mongodb-terminates-when-it-runs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1857685877421545733'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1857685877421545733'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/07/docker-mongodb-terminates-when-it-runs.html' title='Docker MongoDB terminates when it runs out of memory'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-7659002702231806170</id><published>2021-07-04T15:15:00.001+05:30</published><updated>2021-07-04T15:15:41.585+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="NodeJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Peer"/><category scheme="http://www.blogger.com/atom/ns#" term="ReactJs"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><category scheme="http://www.blogger.com/atom/ns#" term="WebRTC"/><title type='text'>ReactJs Peer to Peer Communication</title><content type='html'>&lt;p&gt;Recently I evaluated peer to peer communication approach for one of my project so here I am going to share it and how you can use it in your project in case you want to implement peer to peer communication in your project.&amp;nbsp;&lt;/p&gt;&lt;p&gt;We used library called &lt;a href=&quot;https://peerjs.com/&quot; target=&quot;_blank&quot;&gt;PeerJS&lt;/a&gt;&amp;nbsp;, it&#39;s simple peer to peer built on top of webRTC. For this first you have to create a server, which will act as only connection broker. No peer to peer data goes through this server. Let&#39;s just create a simple server.&lt;/p&gt;&lt;p&gt;Let&#39;s first install peer from npm.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;npm install peer&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Now let&#39;s create NodeJs script.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;const { PeerServer } = require(&#39;peer&#39;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;const peerServer = PeerServer({ port: 9000, path: &#39;/server&#39; });&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;peerServer.on(&#39;connection&#39;, (client) =&amp;gt; {&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;white-space: pre;&quot;&gt;	&lt;/span&gt;console.log(client);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;});&lt;/b&gt;&lt;/p&gt;&lt;p&gt;That&#39;s is now you can run this script through terminal and it will run your server on 9000 port.&lt;/p&gt;&lt;p&gt;Now let&#39;s connect to server from our ReactJS component.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First lets install peerjs npm which is peer client.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;npm install&amp;nbsp;peerjs&lt;/b&gt;&lt;/p&gt;&lt;p&gt;We can connect to server in componentDidMount method and add some callbacks function.&lt;/p&gt;&lt;p&gt;&lt;b&gt;import Peer from &#39;peerjs&#39;;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;componentDidMount = () =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.peer = new Peer(&quot;USERNAME&quot;, {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; host: &#39;localhost&#39;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; port: 9000,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; path: &#39;/server&#39;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;this.peer.on(&quot;error&quot;, err =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; console.log(&quot;error: &quot;, err)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; })&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.peer.on(&quot;open&quot;, id =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; console.log(id)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; })&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; this.peer.on(&quot;connection&quot;, (con) =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; console.log(&quot;connection opened&quot;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; con.on(&quot;data&quot;, i =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; console.log(i)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; })&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;In above code first function is the error callback function. Second once is when peer connection is opened. Third one is when you receive connection from some other peer and get some data.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Now let&#39;s take an example of how you can connect to other peer and send data.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;const conn = this.peer.connect(&#39;REMOTE_PEER&#39;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;conn.on(&#39;open&#39;, () =&amp;gt; {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; conn.send(&#39;DATA&#39;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;});&lt;/b&gt;&lt;/p&gt;&lt;p&gt;In above code we are connecting to some remote peer and sending some data to it.&lt;/p&gt;&lt;p&gt;Please note here peer to peer data goes through ICE server which you can setup and assign when you create peer server or else it will use PeerCloud server by default. For the development purpose that&#39;s ok but for the production you should create your on TURN or STUN server.&lt;/p&gt;&lt;p&gt;Hope this helps you in setting up&amp;nbsp;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/7659002702231806170/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/07/reactjs-peer-to-peer-communication.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7659002702231806170'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7659002702231806170'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/07/reactjs-peer-to-peer-communication.html' title='ReactJs Peer to Peer Communication'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-335957637193132228</id><published>2021-06-26T18:13:00.001+05:30</published><updated>2021-06-26T18:13:22.915+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="ArtificialIntelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="Data Analysis"/><category scheme="http://www.blogger.com/atom/ns#" term="Machine Learning"/><category scheme="http://www.blogger.com/atom/ns#" term="NLP"/><category scheme="http://www.blogger.com/atom/ns#" term="Python"/><category scheme="http://www.blogger.com/atom/ns#" term="TensorFlow"/><title type='text'>Create Question And Answer NLP Model With Bert</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;Recently I worked on POC for chatbot where I evaluated Question Answering with Bert. Here in this blog we will see how you can create Question, Answering with Bert.&lt;/p&gt;&lt;p&gt;&lt;b&gt;What is Bert?&lt;/b&gt;&lt;/p&gt;&lt;p&gt;According to team, who developed Bert&lt;/p&gt;&lt;p&gt;&lt;b&gt;BERT stands for Bidirectional Encoder Representations from Transformers. It is designed to pre-train deep bidirectional representations from unlabelled text by jointly conditioning on both left and right context. As a result, the pre-trained BERT model can be fine-tuned with just one additional output layer to create state-of-the-art models for a wide range of NLP tasks.”&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Bert is pertained on massive dataset and large corpus of unlabelled text. That&#39;s the hidden power of Bert as it uses knowledge gained from pre-training and apply it to dataset given.&amp;nbsp;&lt;/p&gt;&lt;p&gt;For this POC we used HuggingFace&#39;s transformers. So first you have to install transformers. Using this model you can get advantage of pre trained data and then you can pass your reference text to it and this model will try to find answers from it.&lt;/p&gt;&lt;p&gt;&lt;b&gt;pip install transformers&lt;/b&gt;&lt;/p&gt;&lt;p&gt;or&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;pip3 install transformers&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Because this models are very big and it takes time to load and download. Let&#39;s first save it. Create model.py file and add following code.&lt;/p&gt;&lt;p&gt;&lt;b&gt;from transformers import BertForQuestionAnswering&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;from transformers import BertTokenizer&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;BertForQuestionAnswering.from_pretrained(&#39;bert-large-uncased-whole-word-masking-finetuned-squad&#39;).save_pretrained(&#39;./trainedModel&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;BertTokenizer.from_pretrained(&#39;bert-large-uncased-whole-word-masking-finetuned-squad&#39;).save_pretrained(&#39;./trainedModel&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Now execute it with python command. It will create trainedModel directory and save model there with all required files. Now we can load this pertained saved model.&lt;/p&gt;&lt;p&gt;&lt;b&gt;from transformers import BertForQuestionAnswering&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;from transformers import BertTokenizer&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;import torch&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;bertPreTrainedModel = BertForQuestionAnswering.from_pretrained(&#39;./trainedModel&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;tokenizer = BertTokenizer.from_pretrained(&#39;./trainedModel&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;encoded = tokenizer.encode(&#39;YOUR_QUESTION&#39;, &#39;YOUR_REFERENCE_TEXT&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;tokens = tokenizer.convert_ids_to_tokens(encoded)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;sepLocation = encoded.index(tokenizer.sep_token_id)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;first_seg_len, second_seg_len = sepLocation + 1, len(encoded) - (sepLocation + 1)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;seg_embedding = [0] * first_seg_len + [1] * second_seg_len&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;modelScores = bertPreTrainedModel(torch.tensor([encoded]), token_type_ids=torch.tensor([seg_embedding]))&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;ans_start_loc, ans_end_loc = torch.argmax(modelScores[0]), torch.argmax(modelScores[len(modelScores)-1])&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;result = &#39; &#39;.join(tokens[ans_start_loc:ans_end_loc + 1])&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;result = result.replace(&#39; ##&#39;, &#39;&#39;)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Here you will get your answer in result. This way you can develop your model using BERT and transformers.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/335957637193132228/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/06/create-question-and-answer-nlp-model.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/335957637193132228'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/335957637193132228'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/06/create-question-and-answer-nlp-model.html' title='Create Question And Answer NLP Model With Bert'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-7840538758089910482</id><published>2021-06-26T17:33:00.003+05:30</published><updated>2021-06-26T17:33:31.807+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="CSS"/><category scheme="http://www.blogger.com/atom/ns#" term="CSS3"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="React"/><category scheme="http://www.blogger.com/atom/ns#" term="ReactJs"/><category scheme="http://www.blogger.com/atom/ns#" term="UI/UX"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>How to Create Custom Theme for UI using Grommet V2</title><content type='html'>&lt;p&gt;&amp;nbsp;Hello,&lt;/p&gt;&lt;p&gt;In this blog we will understand how you can create custom theme for your using Grommet V2 in your React app.&lt;/p&gt;&lt;p&gt;Using Grommet v2, you can leverage the theme capabilities and define a customTheme as a JS object with your desired colors, margin padding etc. Let&#39;s see how we can do this.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First define your custom theme as JS object. As you can see we have defined some existing grommet color like background, brand. Also we have defined our own color like custom-1, custom-2 etc and then used it in button.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;const customTheme = {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; global: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; colors: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background: &quot;#fff&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; brand: &quot;#000&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;custom-1&quot;: &quot;#aaaaaa&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;custom-2&quot;: &quot;#bbbbbb&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &quot;custom-3&quot;: &quot;#444444&quot;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; },&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; button: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; default: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background: &quot;brand&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; color: &quot;white&quot;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; },&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; primary: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background: &quot;custom-1&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; color: &quot;white&quot;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; },&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; secondary: {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; background: &quot;custom-3&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; color: &quot;dark-2&quot;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;For more information on theme customisation and JSON structure you can visit &lt;a href=&quot;https://v2.grommet.io/grommet&quot; target=&quot;_blank&quot;&gt;Official Grommet site&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Now you can apply this theme to your application as below.&lt;/p&gt;&lt;p&gt;&lt;b&gt;import { Grommet, Box } from &#39;grommet&#39;;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;const DemoGrommet = () =&amp;gt; (&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;lt;Grommet theme={customTheme}&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;Box background=&quot;custom-1&quot; &amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;lt;/Box&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;lt;/Grommet&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;export default DemoGrommet;&lt;/b&gt;&lt;/p&gt;&lt;div&gt;In case you want to keep default values of Grommet theme and want to override only few things with your theme, you can use deepMerge function provided by grommet v2 utils.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;import { deepMerge } from &#39;grommet/utils&#39;;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;import { generate } from &#39;grommet/themes/base&#39;;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;const mergedTheme = deepMerge(generate(16),&amp;nbsp;&lt;/b&gt;&lt;b&gt;customTheme&lt;/b&gt;&lt;b&gt;);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Here generate function generates default theme with 16 pixel font size and then it merge it with your custom theme and provide you updated theme.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/7840538758089910482/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/06/how-to-create-custom-theme-for-ui-using.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7840538758089910482'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7840538758089910482'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/06/how-to-create-custom-theme-for-ui-using.html' title='How to Create Custom Theme for UI using Grommet V2'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-5949908319695761048</id><published>2021-06-26T16:32:00.000+05:30</published><updated>2021-06-26T16:32:11.881+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="CSS3"/><category scheme="http://www.blogger.com/atom/ns#" term="HTML5"/><category scheme="http://www.blogger.com/atom/ns#" term="JavaScript"/><category scheme="http://www.blogger.com/atom/ns#" term="Mobile Website"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Application"/><title type='text'>How to Get Video Thumbnails with Javascript</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;In this blog we will see how you can generate thumbnail of video using JavaScript.&amp;nbsp; Let&#39;s assume you have file upload in your HTML as following.&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;lt;input type=&quot;file&quot; id=&quot;uploadVideo&quot; accept=&quot;video/mp4&quot; /&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;div&gt;Now let&#39;s add an onChange listener for this.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;document.querySelector(&quot;#uploadVideo&quot;).addEventListener(&#39;change&#39;, function() {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; var inputFile =&amp;nbsp;&lt;/span&gt;document.querySelector(&quot;#&lt;/b&gt;&lt;b&gt;uploadVideo&lt;/b&gt;&lt;b&gt;&quot;).files[0];&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;b&gt;getVideoThumbnail(inputFile)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;});&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now when you upload video it will call this function and you can access this video by using files property. Now we got the file. First step we will do is get blob URL of video so we can access metadata of video. Check below function.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here first what we are doing is creating video element and assigning blob URL to it from input file using URL.createObjectURL method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then we have added event listener for meta data. This is necessary as we can&#39;t get video data till them time meta data is loaded.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then we seek video to 0.0 second. You can add your own time here in case if you need. Then we have added seeked listener. By this time we have video data is available. Now we are using canvas to drawImage from video frame data.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Then using toDataURL method we get the base64Data. Here 0.60 is value of quality. If you don&#39;t want to compromise quality of image then you can pass 1 here.&amp;nbsp;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;function getVideoThumbnail(&lt;/b&gt;&lt;b&gt;inputFile&lt;/b&gt;&lt;b&gt;) {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; try {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; let video = document.createElement(&#39;video&#39;);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; let blobSrc = URL.createObjectURL(&lt;/b&gt;&lt;b&gt;inputFile&lt;/b&gt;&lt;b&gt;);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; video.setAttribute(&#39;src&#39;, blobSrc);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; video.addEventListener(&#39;error&#39;, () =&amp;gt; {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; console.log(&quot;Error&quot;)&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; });&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; video.addEventListener(&#39;loadedmetadata&#39;, () =&amp;gt; {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; setTimeout(() =&amp;gt; {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; video.currentTime = 0.0;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }, 200);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; video.addEventListener(&#39;seeked&#39;, () =&amp;gt; {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; let canvas = document.createElement(&#39;canvas&#39;);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; video.pause();&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; canvas.width = 400&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; canvas.height = 400;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; let ctx = canvas.getContext(&#39;2d&#39;);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ctx.drawImage(video, 0, 0, canvas.width, canvas.height);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var base64Data = ctx.canvas.toDataURL(&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;image/png&#39;,&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.60&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; );&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp; // SET this data in SRC of image tag or you can add your own logic.&lt;/span&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; });&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; });&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&amp;nbsp;video.load();&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; } catch (err) {&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; }&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;}&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope this helps you.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/5949908319695761048/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/06/how-to-get-video-thumbnails-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/5949908319695761048'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/5949908319695761048'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/06/how-to-get-video-thumbnails-with.html' title='How to Get Video Thumbnails with Javascript'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-1154396626072300233</id><published>2021-03-19T18:29:00.004+05:30</published><updated>2021-03-19T18:29:53.063+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Apache"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP Framework"/><category scheme="http://www.blogger.com/atom/ns#" term="Server Admin"/><category scheme="http://www.blogger.com/atom/ns#" term="Ubuntu"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>How to solve proxy_fcgi:error AH01071: Got error &#39;Unable to open primary script</title><content type='html'>&lt;p&gt;&amp;nbsp;Hello,&lt;/p&gt;&lt;p&gt;Recently I got stuck with strange bug on centOS server. After I updated document root for my primary domain which has Laravel App installed.&amp;nbsp;&lt;/p&gt;&lt;p&gt;When we try to access app through domain, we got following error.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: medium;&quot;&gt;No input file specified.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I initially thought it&#39;s the permission issue on .htaccess issue. Tried changing permissions and adding some rewrite rules but it didn&#39;t work. When I checked apache error logs. I got following error.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&lt;span style=&quot;font-size: large;&quot;&gt;proxy_fcgi:error AH01071: Got error &#39;Unable to open primary script&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;I had no idea how to solve this error. So tried few things like&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul style=&quot;text-align: left;&quot;&gt;&lt;li&gt;Restart apache&lt;/li&gt;&lt;li&gt;Restart php-fpm&lt;/li&gt;&lt;li&gt;Restart VPS&lt;/li&gt;&lt;li&gt;Removed and added account few times.&lt;/li&gt;&lt;li&gt;Disabling php-fpm&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;But nothing worked. I spent almost entire night in solving this issue but no luck. But finally I was able to solve the issue by following steps. It was actually the issue with php fpm, as it was not able to find out root folder for the domain. So here is what you have to do.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;First go to userdata directory&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;/var/cpanel/userdata/&amp;lt;USERNAME&amp;gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here you will find one file.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;yourdomain.com.php-fpm.yaml&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Open this file with nano or vim editor and add following line at the end of it.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;php_admin_value_doc_root: { name: &#39;php_admin_value[doc_root]&#39;, value: /home/&amp;lt;USERNAME&amp;gt;/public_html/&amp;lt;DOCUMENT_ROOT&amp;gt; }&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Save the file and then execute following commands one by one.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;/scripts/php_fpm_config --rebuild&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;/scripts/restartsrv_apache_php_fpm&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;/scripts/restartsrv_httpd&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This will rebuild php fpm config and restart php fpm service for apache. Now in the same folder open&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;YOURDOMAIN.com&amp;nbsp;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div&gt;YOURDOMAIN.com_SSL&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Change document root here as well and run following commands.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;/scripts/rebuildhttpdconf&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;/scripts/restartsrv_httpd&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This will rebuild apache config file and restart apache.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is it and now if you visit your domain, you will not have the issue of file missing.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope this saves your time&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/1154396626072300233/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2021/03/how-to-solve-proxyfcgierror-ah01071-got.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1154396626072300233'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1154396626072300233'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2021/03/how-to-solve-proxyfcgierror-ah01071-got.html' title='How to solve proxy_fcgi:error AH01071: Got error &#39;Unable to open primary script'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-1097793130146183227</id><published>2020-12-09T17:48:00.004+05:30</published><updated>2020-12-09T17:48:41.960+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Database"/><category scheme="http://www.blogger.com/atom/ns#" term="Database Administrator"/><category scheme="http://www.blogger.com/atom/ns#" term="MySql"/><category scheme="http://www.blogger.com/atom/ns#" term="PhpMyAdmin"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><title type='text'>Restore MySql Database From Just frm and idb File</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;Few days back, I encountered a situation where we needed to restore MySql Database but we only had frm and idb file. Didn&#39;t have .sql file or log file from MySql server which is very much needed when you want to restore. So here in this blog I am going to explain how you can still restore MySql Database from only frm and idb file.&lt;/p&gt;&lt;p&gt;First you will need a tool called&amp;nbsp;dbsake which you can install with following command.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-family: Menlo; font-size: 36px; font-variant-ligatures: no-common-ligatures;&quot;&gt;curl -s http://get.dbsake.net &amp;gt; dbsake&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Once installed, run following command to check if it&#39;s installed properly or not.&amp;nbsp;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;chmod u+x dbsake&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;./dbsake --version&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;If it shows version and all, it&#39;s installed. Now first by using this tool we will get schema of table from frm file. Run following command.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;./dbsake frmdump /PATH_TO_FRM/file.frm&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium;&quot;&gt;It will give you create table schema like this.&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;CREATE TABLE `table_name` (&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column1` int(11) NOT NULL AUTO_INCREMENT,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column2` varchar(255) DEFAULT NULL,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column3` varchar(255) DEFAULT NULL,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; PRIMARY KEY (`column1`)&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8;&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Copy it and run it in your sql editor. If you are migrating it from MySql 5 to 6 you may want to add ROW_FORMAT&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;CREATE TABLE `table_name` (&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column1` int(11) NOT NULL AUTO_INCREMENT,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column2` varchar(255) DEFAULT NULL,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; `column3` varchar(255) DEFAULT NULL,&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;&amp;nbsp; PRIMARY KEY (`column1`)&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=compact;&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Now it will create table. It&#39;s time to load data into it.&amp;nbsp;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;First we will delete the table space which is idb file created. Run following command.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;ALTER TABLE table_name DISCARD TABLESPACE&lt;/b&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Now copy the old idb file and replace the existing one in your MySql server.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;Now attach table space again.&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;b&gt;ALTER TABLE table_name IMPORT TABLESPACE&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;That&#39;s it and now if you browse the data in table, you can see all your old rows.&amp;nbsp;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/1097793130146183227/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/12/restore-mysql-database-from-just-frm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1097793130146183227'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/1097793130146183227'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/12/restore-mysql-database-from-just-frm.html' title='Restore MySql Database From Just frm and idb File'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-6744890510981078951</id><published>2020-09-29T11:17:00.002+05:30</published><updated>2021-02-13T16:13:05.244+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="MAMP"/><category scheme="http://www.blogger.com/atom/ns#" term="MySql"/><category scheme="http://www.blogger.com/atom/ns#" term="PhpMyAdmin"/><category scheme="http://www.blogger.com/atom/ns#" term="SQL"/><title type='text'>MySql Export / Import Large Database</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;In this blog I am going to explain a trick which I recently used for Export / Import large database.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Let me first explain the issue I faced. The database was over 250 MB. I was using MySql WorkBench to export in single self contained file. But it was breaking in between as some tables were really huge.&amp;nbsp;&lt;/p&gt;&lt;p&gt;So here is what I did. First in MySql WorkBench, in stead of exporting it to self contained single file, export it to Dump project folder. Here it will create sql file for each table in the folder. So in my case it created approximately 180 sql files.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Now open terminal and go to that folder. First step here is we will concat all those files and make a single file.&lt;/p&gt;&lt;p&gt;Run the following command in terminal from folder where you have all the sql files.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;cat *.sql&lt;span class=&quot;Apple-converted-space&quot;&gt;&amp;nbsp; &lt;/span&gt;&amp;gt; .single_file.sql&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;Above command will concat all the files into one file and create that file in same folder. Now we will use this file to import into our database.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;/Applications/MAMP/Library/bin/mysql -u DB_USER -p DB &amp;lt; .single_file.sql&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class=&quot;p1&quot; style=&quot;font-family: Menlo; font-size: 36px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: normal; margin: 0px;&quot;&gt;&lt;span class=&quot;s1&quot; style=&quot;font-variant-ligatures: no-common-ligatures;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium; font-variant-ligatures: normal;&quot;&gt;That&#39;s it. With this trick you can Import / Export large database. Please note that, for this you should have terminal access to your MySql server.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/6744890510981078951/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/09/mysql-export-import-large-database.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6744890510981078951'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/6744890510981078951'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/09/mysql-export-import-large-database.html' title='MySql Export / Import Large Database'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-2510506803143641313</id><published>2020-09-07T11:41:00.002+05:30</published><updated>2020-09-07T11:41:40.816+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Android App"/><category scheme="http://www.blogger.com/atom/ns#" term="Android Application"/><category scheme="http://www.blogger.com/atom/ns#" term="Android SDK"/><category scheme="http://www.blogger.com/atom/ns#" term="Socket"/><category scheme="http://www.blogger.com/atom/ns#" term="WebSocket"/><title type='text'>Connect to Web Socket From Your Android App using OkHttp</title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;In this blog I am going to explain how you can connect with Web Socket from your Android App using OkHttp. This will be useful when you want to send some data real time from your Android app to Web app.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First add following line in your build.gradle file dependencies.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;implementation &#39;com.squareup.okhttp3:okhttp:3.11.0&#39;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Now let the gradle build and sync. Next we will make a class which extends&amp;nbsp;WebSocketListener from OkHttp3 and a new class and name it MyWebSocketListener.java and add following code to it.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;import okhttp3.Response;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;import okhttp3.WebSocket;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;import okhttp3.WebSocketListener;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;import okio.ByteString;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;public final class MyWebSocketListener extends WebSocketListener {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; private static final int NORMAL_CLOSURE_STATUS = 5000;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public MyWebSocketListener() {&amp;nbsp;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; @Override&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public void onOpen(WebSocket webSocket, Response response) {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; webSocket.close(NORMAL_CLOSURE_STATUS, &quot;Exit&quot;);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; @Override&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public void onMessage(WebSocket webSocket, String text) {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //String Meesage received&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; @Override&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public void onMessage(WebSocket webSocket, ByteString bytes) {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //Meesage received in form of binary data&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; @Override&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public void onClosing(WebSocket webSocket, int code, String reason) {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; webSocket.close(NORMAL_CLOSURE_STATUS, null);&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; //Closing socket&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; @Override&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; public void onFailure(WebSocket webSocket, Throwable t, Response response) {&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; t.printStackTrace();&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; }&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;}&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Now we have listener created. Let&#39;s create client and attach it to Web Socket and Listener.&lt;/p&gt;&lt;p&gt;&lt;b&gt;val listener =&amp;nbsp;MyWebSocketListener()&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;val webSocket =&amp;nbsp; &amp;nbsp;OkHttpClient.Builder().build().newWebSocket(request, listener)&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;That&#39;s it, now you can use this instance to send or receive message.&lt;/p&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/2510506803143641313/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/09/connect-to-web-socket-from-your-android.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/2510506803143641313'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/2510506803143641313'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/09/connect-to-web-socket-from-your-android.html' title='Connect to Web Socket From Your Android App using OkHttp'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-4311390403293044766</id><published>2020-09-05T12:55:00.002+05:30</published><updated>2020-09-05T12:55:16.917+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="Ratchet"/><category scheme="http://www.blogger.com/atom/ns#" term="Socket"/><category scheme="http://www.blogger.com/atom/ns#" term="Web Development"/><title type='text'>Create Secure Web Socket (WSS) with Ratchet PHP </title><content type='html'>&lt;p&gt;Hello,&lt;/p&gt;&lt;p&gt;Recently I was working on PHP project where we I was create secure web socket which is accessible with wss:// protocol. For this I struggled for couple of hours so here in blog I am going to explain how to do that so it can save your time.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Earlier version was not supporting WSS but later it introduced React socket server which allows SSL connection. So here are steps you need to follow.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First add all the required classed in your php file.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;use Ratchet\Server\IoServer;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;use Ratchet\Http\HttpServer;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;use Ratchet\WebSocket\WsServer;&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;use MyApp\Socket;&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In above example Socket is my class file which has all listeners. After this add auto load file.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;require dirname( __FILE__ ) . &#39;/vendor/autoload.php&#39;;&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Next we will create our socket app.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;$app = new \Ratchet\Http\HttpServer(&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; new \Ratchet\WebSocket\WsServer(&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; new \MyApp\Socket()&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; )&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;);&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now next step is to create React Secure server.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;$loop = \React\EventLoop\Factory::create();&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;$webSock = new \React\Socket\Server(&#39;0.0.0.0:8080&#39;, $loop);&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;We are using 0.0.0.0&amp;nbsp; so this socket can be connected from anywhere.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now lets create secure server by adding path to certificate and key&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;$webSock = new \React\Socket\SecureServer($webSock, $loop, [&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&#39;local_cert&#39; =&amp;gt; &#39;CRT_PATH&#39;,&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&#39;local_pk&#39;=&amp;gt; &#39;KEY_PATH&#39;,&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&#39;allow_self_signed&#39; =&amp;gt; true,&amp;nbsp;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&#39;verify_peer&#39; =&amp;gt; false&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;]);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;Now finally we will run our server.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;b&gt;$webSock = new \Ratchet\Server\IoServer($app, $webSock, $loop);&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;$webSock-&amp;gt;run();&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;That&#39;s it. It will start your server to which you can connect with WSS protocol. To test you can use WebSocket ECHO test.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href=&quot;https://www.websocket.org/echo.html&quot;&gt;https://www.websocket.org/echo.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Hope this helps you.&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/4311390403293044766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/09/create-secure-web-socket-wss-with.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4311390403293044766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/4311390403293044766'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/09/create-secure-web-socket-wss-with.html' title='Create Secure Web Socket (WSS) with Ratchet PHP '/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-76004663673923913</id><published>2020-08-20T16:04:00.001+05:30</published><updated>2020-08-20T16:04:07.450+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Laravel"/><category scheme="http://www.blogger.com/atom/ns#" term="Laravel 5.2"/><category scheme="http://www.blogger.com/atom/ns#" term="Laravel 5.4"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP"/><category scheme="http://www.blogger.com/atom/ns#" term="PHP Framework"/><title type='text'>AWS PHP SDK - Create an Entry in Route53 - Laravel</title><content type='html'>&lt;p&gt;&amp;nbsp;Hello,&lt;/p&gt;&lt;p&gt;In this blog I will explain you how to you can create an entry in Route53 hosted zone using AWS PHP SDK. Solution I mentioned here is particularly for Laravel app, but you can still use it in any of the PHP project.&amp;nbsp;&lt;/p&gt;&lt;p&gt;This solution is pretty much useful when you want to make a dynamic entry in your hosted. For example a dynamic sub domain creation.&amp;nbsp;&lt;/p&gt;&lt;p&gt;First of all your need install couple of packages using composer. Following are the packages.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&quot;aws/aws-sdk-php&quot;: &quot;^3.148&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;&lt;b&gt;&quot;aws/aws-sdk-php-laravel&quot;: &quot;~3.0&quot;,&lt;/b&gt;&lt;/p&gt;&lt;p&gt;You can either install it by adding it in composer.json file or you can install it using composer require.&amp;nbsp;&lt;/p&gt;&lt;p&gt;Once the installation is done, follow the steps mentioned in below URL.&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: x-large;&quot;&gt;&lt;a href=&quot;https://github.com/aws/aws-sdk-php-laravel&quot;&gt;https://github.com/aws/aws-sdk-php-laravel&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;Once installation is done. You need to add following keys in your env file.&lt;/p&gt;&lt;p&gt;AWS_ACCESS_KEY_ID&lt;/p&gt;&lt;p&gt;AWS_SECRET_ACCESS_KEY&lt;/p&gt;&lt;p&gt;AWS_REGION (default = us-east-1)&lt;/p&gt;&lt;p&gt;Set the values in above keys from your AWS account. That&#39;s it your AWS SDK is ready. Now add following line your controller where you want to have logic for adding value in Route53&lt;/p&gt;&lt;p&gt;use Aws\Route53\Route53Client;&lt;/p&gt;&lt;p&gt;use Aws\Common\Credentials\Credentials;&lt;/p&gt;&lt;p&gt;Now next step is to create a client&lt;/p&gt;&lt;p&gt;$client = Route53Client::factory(array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;credentials&#39; =&amp;gt; config(&#39;aws.credentials&#39;),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;region&#39; =&amp;gt; config(&#39;aws.region&#39;),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;version&#39; =&amp;gt; config(&#39;aws.version&#39;),&lt;/p&gt;&lt;p&gt;));&amp;nbsp;&lt;/p&gt;&lt;p&gt;After client is created we will use&amp;nbsp;changeResourceRecordSets to create an entry.&lt;/p&gt;&lt;p&gt;$result = $client-&amp;gt;changeResourceRecordSets(array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // HostedZoneId is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;HostedZoneId&#39; =&amp;gt; &#39;YOUR_HOSTED_ZONE_ID&#39;,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // ChangeBatch is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;ChangeBatch&#39; =&amp;gt; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Comment&#39; =&amp;gt; &#39;string&#39;,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Changes is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Changes&#39; =&amp;gt; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Action is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Action&#39; =&amp;gt; &#39;CREATE&#39;,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // ResourceRecordSet is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;ResourceRecordSet&#39; =&amp;gt; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Name is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Name&#39; =&amp;gt; &#39;YOUR_VALUE&#39;,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Type is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Type&#39; =&amp;gt; &#39;CNAME&#39;, //A, CANME&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;TTL&#39; =&amp;gt; 600,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;ResourceRecords&#39; =&amp;gt; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; array(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Value is required&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &#39;Value&#39; =&amp;gt; &#39;YOUR_VALUE&#39;, //IP address or load balancer.&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ),&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ));&lt;/p&gt;&lt;div&gt;That&#39;s it and it will create an entry in Route53 hosted zone.&amp;nbsp;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/76004663673923913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/08/aws-php-sdk-create-entry-in-route53.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/76004663673923913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/76004663673923913'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/08/aws-php-sdk-create-entry-in-route53.html' title='AWS PHP SDK - Create an Entry in Route53 - Laravel'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7442072150765022610.post-7202062603290500057</id><published>2020-08-04T15:45:00.005+05:30</published><updated>2020-08-04T15:45:59.774+05:30</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="Android App"/><category scheme="http://www.blogger.com/atom/ns#" term="Android Application"/><category scheme="http://www.blogger.com/atom/ns#" term="Android SDK"/><category scheme="http://www.blogger.com/atom/ns#" term="FireBase"/><title type='text'>Android Build Error - The Crashlytics build ID is missing</title><content type='html'>Hello,&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Recently I faced a very strange issue in one of my android app. We were using Fabric IO for crash analytics earlier in the app and since now it&#39;s already merged with Firebase Analytics. we need to update the app.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I removed Firebase maven repository and removed all plugins from build gradle file and removed Fabric code from everywhere. And build was successful. After that I followed all the instructions on getting started page of Firebase and crash analytics and build was successful.&amp;nbsp; And then problem started. Once we run the app, it crashes and shows following error in Logcat.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&quot;&lt;b&gt;The Crashlytics build ID is missing. This occurs when Crashlytics tooling is absent from your app&#39;s build configuration. Please review Crashlytics onboarding instructions and ensure you have a valid Crashlytics account&lt;/b&gt;&quot;&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now it seems there is an issue with Firebase crash analytics account so I regenerated the google service json file add updated in project. But it didn&#39;t help.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Searched on Google, answers suggest to put back Fabric plugin again in gradle file. Which does not make any sense to me. Since Fabric is out dated, why do we need to add it again.&amp;nbsp;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally after 2 days I was able to solve the problem. Here is the solution&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div class=&quot;css-1dbjc4n r-a1ub67&quot; style=&quot;-webkit-box-align: stretch; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: stretch; background-color: white; border: 0px solid black; box-sizing: border-box; display: flex; flex-basis: auto; flex-direction: column; flex-shrink: 0; margin: 11px 0px 0px; min-height: 0px; min-width: 0px; padding: 0px; position: relative; z-index: 0;&quot;&gt;&lt;div class=&quot;css-901oao r-hkyrab r-1qd0xha r-1x35g6 r-16dba41 r-ad9z0x r-bcqeeo r-bnwqim r-qvutc0&quot; dir=&quot;auto&quot; lang=&quot;en&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: #14171a; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 24px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; position: relative; white-space: pre-wrap;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: inherit; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: inherit;&quot;&gt;Remove google service json file. Use Firebase assistant and connect with your account again. Select the project and it again generate google service json file. Keep link to fabric io repository in top level gradle file.&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;css-901oao r-hkyrab r-1qd0xha r-1x35g6 r-16dba41 r-ad9z0x r-bcqeeo r-bnwqim r-qvutc0&quot; dir=&quot;auto&quot; lang=&quot;en&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: #14171a; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 24px; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; position: relative; white-space: pre-wrap;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: inherit; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: inherit;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;css-901oao r-hkyrab r-1qd0xha r-1x35g6 r-16dba41 r-ad9z0x r-bcqeeo r-bnwqim r-qvutc0&quot; dir=&quot;auto&quot; lang=&quot;en&quot; style=&quot;border: 0px solid black; box-sizing: border-box; display: inline; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; position: relative;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; display: inline; font-size: 24px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: pre-wrap;&quot;&gt;&lt;font color=&quot;#14171a&quot; face=&quot;system-ui, -apple-system, system-ui, Segoe UI, Roboto, Ubuntu, Helvetica Neue, sans-serif&quot;&gt;maven {
            url &#39;https://maven.fabric.io/public&#39;
}&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class=&quot;css-901oao r-hkyrab r-1qd0xha r-1x35g6 r-16dba41 r-ad9z0x r-bcqeeo r-bnwqim r-qvutc0&quot; dir=&quot;auto&quot; lang=&quot;en&quot; style=&quot;border: 0px solid black; box-sizing: border-box; display: inline; font-stretch: normal; font-variant-east-asian: normal; font-variant-numeric: normal; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; position: relative;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; display: inline; font-size: 24px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: pre-wrap;&quot;&gt;&lt;font color=&quot;#14171a&quot; face=&quot;system-ui, -apple-system, system-ui, Segoe UI, Roboto, Ubuntu, Helvetica Neue, sans-serif&quot;&gt;&lt;br /&gt;&lt;/font&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 16px;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: inherit; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: inherit;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium;&quot;&gt;I don&#39;t know how it worked but it works and I really don&#39;t know the reason of why it didn&#39;t work and why it started working after above solution. But it does solve the problem.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 16px;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: inherit; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: inherit;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style=&quot;font-size: 16px;&quot;&gt;&lt;span class=&quot;css-901oao css-16my406 r-1qd0xha r-ad9z0x r-bcqeeo r-qvutc0&quot; style=&quot;border: 0px solid black; box-sizing: border-box; color: inherit; display: inline; font-family: system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: inherit; font-stretch: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; line-height: 1.3125; margin: 0px; min-width: 0px; overflow-wrap: break-word; padding: 0px; white-space: inherit;&quot;&gt;&lt;span style=&quot;font-family: Times; font-size: medium;&quot;&gt;If anyone who is reading this blog, knows the reason please put in comment.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;css-1dbjc4n r-1r5su4o&quot; style=&quot;-webkit-box-align: stretch; -webkit-box-direction: normal; -webkit-box-orient: vertical; align-items: stretch; background-color: white; border: 0px solid black; box-sizing: border-box; display: flex; flex-basis: auto; flex-direction: column; flex-shrink: 0; font-size: 16px; margin: 16px 0px; min-height: 0px; min-width: 0px; padding: 0px; position: relative; z-index: 0;&quot;&gt;&lt;div class=&quot;css-1dbjc4n r-1awozwy r-18u37iz r-1wtj0ep&quot; style=&quot;-webkit-box-align: center; -webkit-box-direction: normal; -webkit-box-orient: horizontal; -webkit-box-pack: justify; align-items: center; border: 0px solid black; box-sizing: border-box; display: flex; flex-basis: auto; flex-direction: row; flex-shrink: 0; justify-content: space-between; margin: 0px; min-height: 0px; min-width: 0px; padding: 0px; position: relative; z-index: 0;&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://www.hiren.dev/feeds/7202062603290500057/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.hiren.dev/2020/08/android-build-error-crashlytics-build.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7202062603290500057'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7442072150765022610/posts/default/7202062603290500057'/><link rel='alternate' type='text/html' href='http://www.hiren.dev/2020/08/android-build-error-crashlytics-build.html' title='Android Build Error - The Crashlytics build ID is missing'/><author><name>Hiren Dave</name><uri>http://www.blogger.com/profile/03332234242233370508</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='//blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiSTrKrW2hF0Kl2lmUdqLsKOP9A_ozB4Obt1iH0UDqVNggVbKZwhS3WIP900JH6-bD2w543VZB3_d86_0Qc1ALAdCzEzctBOl5Lc1ahty0JtXza0rgpVEkId2j0KAF4-w/s220/hirendave12.png'/></author><thr:total>1</thr:total></entry></feed>