<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: rising_segun</title>
    <description>The latest articles on DEV Community by rising_segun (@geosegun).</description>
    <link>https://dev.to/geosegun</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1049039%2Fd73240a0-ad90-443e-b320-009a1544e0f4.jpeg</url>
      <title>DEV Community: rising_segun</title>
      <link>https://dev.to/geosegun</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/geosegun"/>
    <language>en</language>
    <item>
      <title>Mintlify vs. Docusaurus vs. GitBook: Detailed Comparison (2026)</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Tue, 18 Aug 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/reclear/mintlify-vs-docusaurus-vs-gitbook-detailed-comparison-2026-1nd5</link>
      <guid>https://dev.to/reclear/mintlify-vs-docusaurus-vs-gitbook-detailed-comparison-2026-1nd5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5g5rg0f6mfw46tnicy3m.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5g5rg0f6mfw46tnicy3m.webp" alt="Mintlify vs. Docusaurus vs. GitBook: Detailed Comparison (2026)" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mintlify, Docusaurus, and GitBook are the three most popular documentation tools for &lt;a href="https://reclear.io/blog/developer-documentation-that-gets-used" rel="noopener noreferrer"&gt;developer documentation&lt;/a&gt;. Choosing between these tools comes down to how much control you want, how your team writes and publishes docs, and how much infrastructure you want to manage.&lt;/p&gt;

&lt;p&gt;This guide compares the three across setup, writing workflow, customization, API documentation, versioning, search, AI features, analytics, SEO, hosting, maintenance, and pricing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Mintlify&lt;/strong&gt; suits developer teams that want a managed docs platform with Git-based workflows and built-in publishing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docusaurus&lt;/strong&gt; gives you the most control, but your team handles deployment and maintenance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitBook&lt;/strong&gt; is a strong fit for teams that want easier collaboration between technical and nontechnical contributors.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API documentation&lt;/strong&gt; is more nuanced. Mintlify and GitBook offer dedicated features, while Docusaurus usually needs extra tooling.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;There is no single winner&lt;/strong&gt;. Choose based on workflow, control, maintenance, and team structure.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Comparison at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Mintlify&lt;/th&gt;
&lt;th&gt;Docusaurus&lt;/th&gt;
&lt;th&gt;GitBook&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pricing model&lt;/td&gt;
&lt;td&gt;Free Starter; paid Pro and Enterprise plans&lt;/td&gt;
&lt;td&gt;Free and open source; you pay for hosting and any third-party services&lt;/td&gt;
&lt;td&gt;Free plan; paid site plans start at $65/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Developer teams that want managed docs with Git workflows&lt;/td&gt;
&lt;td&gt;Engineering teams that want full control and customization&lt;/td&gt;
&lt;td&gt;Teams that want managed docs with strong browser-based collaboration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Time to first deploy&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;td&gt;Depends on setup and hosting&lt;/td&gt;
&lt;td&gt;Minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;Managed by Mintlify&lt;/td&gt;
&lt;td&gt;You choose and manage hosting&lt;/td&gt;
&lt;td&gt;Managed by GitBook&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Setup difficulty&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Medium to high&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Git workflow&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;td&gt;Native Git workflow&lt;/td&gt;
&lt;td&gt;GitHub and GitLab sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customization&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Very high&lt;/td&gt;
&lt;td&gt;Moderate to high&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API docs&lt;/td&gt;
&lt;td&gt;Built-in API playground and OpenAPI support&lt;/td&gt;
&lt;td&gt;Usually requires plugins or custom tooling&lt;/td&gt;
&lt;td&gt;Built-in OpenAPI and interactive API docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Versioning&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;td&gt;Built in through the versioning CLI&lt;/td&gt;
&lt;td&gt;Supported through site variants&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;td&gt;Algolia or other search integrations&lt;/td&gt;
&lt;td&gt;Built in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI features&lt;/td&gt;
&lt;td&gt;AI assistant, agent features, MCP&lt;/td&gt;
&lt;td&gt;Available through integrations such as Algolia Ask AI&lt;/td&gt;
&lt;td&gt;AI search, AI Assistant, MCP, LLM optimizations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Built-in insights&lt;/td&gt;
&lt;td&gt;Requires third-party analytics&lt;/td&gt;
&lt;td&gt;Built-in site insights&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;td&gt;Low&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  What is Mintlify, Docusaurus, and GitBook?
&lt;/h2&gt;

&lt;p&gt;Mintlify, Docusaurus, and GitBook can all power developer documentation, but they take different approaches to how teams build, publish, and maintain it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mintlify: Managed docs for developer teams
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6uffr6ofrv9n7ua00dqn.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6uffr6ofrv9n7ua00dqn.webp" alt="Mintlify homepage showing its developer documentation platform" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.mintlify.com/docs" rel="noopener noreferrer"&gt;Mintlify&lt;/a&gt; is a managed documentation platform built around a Git and MDX workflow. Developers can work locally and submit changes through Git, while other contributors can make changes through its web editor. Mintlify handles the documentation site's build, deployment, and hosting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Developer-focused teams that want docs-as-code without maintaining the documentation infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Supports Git-based and browser editing.&lt;/li&gt;
&lt;li&gt;Handles hosting and deployment.&lt;/li&gt;
&lt;li&gt;Supports OpenAPI-generated API documentation and interactive API features.&lt;/li&gt;
&lt;li&gt;Includes built-in search and AI features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offers less infrastructure control than a self-hosted solution.&lt;/li&gt;
&lt;li&gt;Advanced features and larger teams require paid plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Docusaurus: Open source with more control
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv971hor2iqkoepiwjll1.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fv971hor2iqkoepiwjll1.webp" alt="Docusaurus homepage showing its open-source documentation website builder" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docusaurus.io/docs" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt; is an open-source static site generator maintained by Meta. Documentation is written in Markdown or MDX and compiled into a static website. Unlike Mintlify and GitBook, Docusaurus does not provide a managed documentation service. Your team chooses the hosting provider and controls the deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Engineering teams that want more control over their documentation site and are comfortable managing the underlying setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free and open source.&lt;/li&gt;
&lt;li&gt;Highly customizable with React.&lt;/li&gt;
&lt;li&gt;Supports documentation versioning.&lt;/li&gt;
&lt;li&gt;Gives you control over hosting and deployment.&lt;/li&gt;
&lt;li&gt;Has a large plugin and integration ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires more setup and ongoing maintenance.&lt;/li&gt;
&lt;li&gt;Search, analytics, and some documentation features may require third-party services or additional configuration.&lt;/li&gt;
&lt;li&gt;Less accessible to nontechnical contributors without a separate editorial workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GitBook: Managed docs for collaborative teams
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwm93py9mm6yx3r08k2k9.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwm93py9mm6yx3r08k2k9.webp" alt="GitBook homepage showing its collaborative documentation platform" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gitbook.com/docs" rel="noopener noreferrer"&gt;GitBook&lt;/a&gt; is a managed documentation platform that combines browser-based editing with Git workflows. Teams can create and edit documentation in GitBook or use Git Sync to keep content synchronized with GitHub or GitLab. GitBook handles publishing and hosting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want developers and nontechnical contributors to work on the same documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual editor for browser-based writing.&lt;/li&gt;
&lt;li&gt;GitHub and GitLab synchronization.&lt;/li&gt;
&lt;li&gt;Managed hosting and publishing.&lt;/li&gt;
&lt;li&gt;Built-in search and AI capabilities.&lt;/li&gt;
&lt;li&gt;Supports OpenAPI-based API documentation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Less control over the underlying infrastructure than Docusaurus.&lt;/li&gt;
&lt;li&gt;Some advanced publishing and collaboration features require paid plans.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; Mintlify prioritizes the developer workflow, Docusaurus gives you the most control, and GitBook makes collaborative authoring easier. The rest of this comparison looks at where those differences matter in practice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mintlify vs. Docusaurus vs. GitBook: Feature comparison
&lt;/h2&gt;

&lt;p&gt;The biggest differences between these tools show up in how teams build, maintain, and use their documentation. Let's compare the six areas that matter most.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Setup and deployment&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Writing and collaboration&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customization&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;API documentation&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versioning&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Search and AI features&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Mintlify vs. Docusaurus vs. GitBook pricing
&lt;/h2&gt;

&lt;p&gt;The three tools use different pricing models. Mintlify and GitBook charge for managed platforms, while Docusaurus is free and open source but leaves hosting and maintenance to your team.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mintlify pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.mintlify.com/pricing" rel="noopener noreferrer"&gt;Mintlify has three plans&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Starter:&lt;/strong&gt; Free. Includes five editor seats, Git sync, a custom domain, web editor, search, API playground, authentication, and an MCP server.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro: $450 per month billed annually or $540 per month billed monthly&lt;/strong&gt;. Includes unlimited editor seats and adds preview deployments, Agent, Assistant, Automations, and admin APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom pricing. Adds SSO, SCIM, role-based access control (RBAC), advanced insights, a performance SLA, migration support, and enterprise security features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is also a usage cost to consider on Pro. Mintlify includes &lt;strong&gt;10,000 credits per month&lt;/strong&gt; for its AI features and charges &lt;strong&gt;$0.01 per credit&lt;/strong&gt; for overages.&lt;/p&gt;

&lt;p&gt;For a small team, the free Starter plan covers much of the core documentation workflow. The price jump comes when you need features such as preview deployments, AI agents, automations, or enterprise controls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docusaurus pricing
&lt;/h3&gt;

&lt;p&gt;Docusaurus is &lt;strong&gt;free and open source&lt;/strong&gt;. There are no per-user, per-site, or Docusaurus subscription fees.&lt;/p&gt;

&lt;p&gt;The cost comes from running it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docusaurus.io/docs/deployment" rel="noopener noreferrer"&gt;Docusaurus builds your documentation into static files&lt;/a&gt; and leaves hosting to you. You can deploy those files to GitHub Pages, Vercel, Netlify, Render, your own server, or another static hosting provider.&lt;/p&gt;

&lt;p&gt;Some costs can stay at $0:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Pages provides free build and deployment for public repositories.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docsearch.algolia.com/docs/who-can-apply/" rel="noopener noreferrer"&gt;Algolia DocSearch is free&lt;/a&gt; for eligible public developer documentation and technical blogs.&lt;/li&gt;
&lt;li&gt;Some static hosting providers offer free tiers that may be enough for smaller documentation sites.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But a production setup can introduce costs for hosting, private search, analytics, continuous integration and continuous deployment (CI/CD), monitoring, and other services.&lt;/p&gt;

&lt;p&gt;The largest hidden cost is often &lt;strong&gt;engineering time&lt;/strong&gt;. Your team owns the build configuration, dependencies, deployment pipeline, upgrades, integrations, and any custom React components.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitBook pricing
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.gitbook.com/pricing" rel="noopener noreferrer"&gt;GitBook charges per published site and per collaborating user&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free:&lt;/strong&gt; $0, with one user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Premium: $65 per site per month&lt;/strong&gt; when billed annually, plus &lt;strong&gt;$12 per user per month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ultimate: $249 per site per month&lt;/strong&gt; when billed annually, plus &lt;strong&gt;$12 per user per month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise:&lt;/strong&gt; Custom pricing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Premium adds features such as custom domains, AI search, analytics, user feedback, redirects, and advanced branding. Ultimate adds GitBook's AI Assistant and other advanced features.&lt;/p&gt;

&lt;p&gt;For example, a five-person team running one Premium documentation site would cost:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$65 + (5 × $12) = $125 per month&lt;/code&gt;, or &lt;code&gt;$1,500 per year&lt;/code&gt; at the published annual-billing rate.&lt;/p&gt;

&lt;p&gt;The same five-person team on Ultimate would pay:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$249 + (5 × $12) = $309 per month&lt;/code&gt;, or &lt;code&gt;$3,708 per year&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;GitBook does not charge based on documentation traffic. Page views are unlimited across its plans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total cost of ownership:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The subscription price doesn't tell the whole story.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;th&gt;Mintlify&lt;/th&gt;
&lt;th&gt;Docusaurus&lt;/th&gt;
&lt;th&gt;GitBook&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Platform&lt;/td&gt;
&lt;td&gt;$0; Pro from $450/month when billed annually&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0; Premium from $65/month when billed annually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Additional users&lt;/td&gt;
&lt;td&gt;Included by plan&lt;/td&gt;
&lt;td&gt;$0 platform fee&lt;/td&gt;
&lt;td&gt;$12/user/month on paid plans&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hosting&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;You provide it&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Search&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;Separate; can be free&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;td&gt;You manage it&lt;/td&gt;
&lt;td&gt;Managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintenance&lt;/td&gt;
&lt;td&gt;Mostly managed&lt;/td&gt;
&lt;td&gt;Your team&lt;/td&gt;
&lt;td&gt;Mostly managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI usage costs&lt;/td&gt;
&lt;td&gt;Credits and possible overages&lt;/td&gt;
&lt;td&gt;Depends on tooling&lt;/td&gt;
&lt;td&gt;Included features vary by plan&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; Compare the subscription price with the engineering time your team will spend running the documentation stack. For Docusaurus in particular, "$0" describes the software license, not necessarily the cost of ownership.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you choose Mintlify?
&lt;/h2&gt;

&lt;p&gt;Choose &lt;a href="https://www.mintlify.com/docs" rel="noopener noreferrer"&gt;Mintlify&lt;/a&gt; if you want a developer-focused documentation platform without owning the infrastructure.&lt;/p&gt;

&lt;p&gt;Mintlify is a good fit if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your developers already work in Git.&lt;/strong&gt; Documentation can live in the repository and follow the same branch, pull request, and review workflow as code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want managed docs without giving up docs-as-code.&lt;/strong&gt; Mintlify handles hosting and deployment while your team works with MDX and Git.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://reclear.io/blog/what-makes-great-api-documentation" rel="noopener noreferrer"&gt;API documentation&lt;/a&gt; is a core part of your docs.&lt;/strong&gt; Mintlify supports OpenAPI-generated references and an interactive API playground.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want AI features built into the documentation platform.&lt;/strong&gt; Mintlify provides AI search and assistant features, &lt;code&gt;llms.txt&lt;/code&gt;, MCP support, and tools for making documentation available to AI agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You don't want engineers maintaining the docs stack.&lt;/strong&gt; You give up some infrastructure control, but you also avoid managing builds, hosting, search, and much of the deployment pipeline.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip Mintlify if:&lt;/strong&gt; You need full control over the frontend or want to self-host the entire documentation stack.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best fit:&lt;/strong&gt; Developer tools, APIs, SDKs, and technical products with engineering-led documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you choose Docusaurus?
&lt;/h2&gt;

&lt;p&gt;Choose &lt;a href="https://docusaurus.io/docs" rel="noopener noreferrer"&gt;Docusaurus&lt;/a&gt; if control matters more than convenience.&lt;/p&gt;

&lt;p&gt;Docusaurus is a good fit if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your team is comfortable with React.&lt;/strong&gt; You can build custom components, layouts, themes, and documentation experiences instead of staying within a managed platform's boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want to control hosting and deployment.&lt;/strong&gt; Docusaurus generates static files that you can deploy through your existing infrastructure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your docs need heavy customization.&lt;/strong&gt; This is useful when documentation needs to share components, branding, or functionality with the rest of your developer experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You already have engineering resources for the docs stack.&lt;/strong&gt; Maintaining dependencies, CI/CD, hosting, search, plugins, and upgrades is less of a problem when someone owns them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want an open-source foundation.&lt;/strong&gt; Docusaurus itself has no platform subscription or per-user fee.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip Docusaurus if:&lt;/strong&gt; You want a documentation platform your team can publish and maintain with little engineering involvement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best fit:&lt;/strong&gt; Engineering-led teams that value customization, infrastructure ownership, and extensibility over a managed experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should you choose GitBook?
&lt;/h2&gt;

&lt;p&gt;Choose &lt;a href="https://gitbook.com/docs" rel="noopener noreferrer"&gt;GitBook&lt;/a&gt; if documentation is shared across engineering, product, support, and other teams.&lt;/p&gt;

&lt;p&gt;GitBook is a good fit if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Not everyone writing documentation uses Git.&lt;/strong&gt; Contributors can work in GitBook's visual editor without managing repositories or local development environments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers still need a Git workflow.&lt;/strong&gt; Git Sync connects documentation with GitHub or GitLab, so technical contributors don't have to abandon their existing workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Collaboration matters more than frontend control.&lt;/strong&gt; GitBook handles publishing and hosting while giving teams tools for editing, reviewing, and managing content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You need public and private documentation.&lt;/strong&gt; GitBook supports published documentation as well as authenticated access for restricted content.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You want API docs without building the tooling yourself.&lt;/strong&gt; GitBook can generate interactive API documentation from OpenAPI specifications.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Skip GitBook if:&lt;/strong&gt; Deep frontend customization or complete infrastructure ownership is a requirement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best fit:&lt;/strong&gt; Cross-functional teams that need developers and nontechnical contributors to maintain documentation together.&lt;/p&gt;

&lt;p&gt;Here is a quick decision. If you're still deciding, reduce it to one question:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Want a managed platform built around developer workflows?&lt;/strong&gt; Choose Mintlify.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Want maximum control and don't mind maintaining the stack?&lt;/strong&gt; Choose Docusaurus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Want developers and nontechnical teams contributing together?&lt;/strong&gt; Choose GitBook.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Final Take
&lt;/h2&gt;

&lt;p&gt;Mintlify offers a managed, developer-focused workflow, Docusaurus gives engineering teams more control, and GitBook makes it easier for technical and nontechnical teams to work on documentation together. The right choice depends on how your team works and how much of the documentation stack you want to manage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Need help with your developer documentation?
&lt;/h2&gt;

&lt;p&gt;Choosing the right platform is only part of the job. &lt;a href="https://reclear.io" rel="noopener noreferrer"&gt;Reclear&lt;/a&gt; helps developer-first teams plan, build, and improve documentation for APIs, SDKs, and technical products across Mintlify, Docusaurus, GitBook, and other documentation stacks.&lt;/p&gt;

&lt;p&gt;We also offer a free documentation audit to identify gaps in your structure, content, developer experience, and tooling.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reclear.io/book-a-call" rel="noopener noreferrer"&gt;Book a call with Reclear&lt;/a&gt;&lt;/p&gt;

</description>
      <category>documentation</category>
    </item>
    <item>
      <title>10 Best PaaS Providers for Web Apps in 2026</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Sat, 18 Jul 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/seenode/10-best-paas-providers-for-web-apps-in-2026-3b54</link>
      <guid>https://dev.to/seenode/10-best-paas-providers-for-web-apps-in-2026-3b54</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4vas6x2l96k9jva5drem.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4vas6x2l96k9jva5drem.webp" alt="10 Best PaaS Providers for Web Apps in 2026" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Platform-as-a-service (PaaS) lets you deploy a web app without provisioning servers, patching OSes, or wiring CI/CD from scratch. You push code (usually from GitHub or GitLab) and the platform handles builds, SSL, routing, and scaling.&lt;/p&gt;

&lt;p&gt;That is different from static hosting. A real web app needs a process that stays up, talks to a database, runs background jobs, and often keeps WebSockets or long-lived connections open. The best PaaS for that job is not always the same one that wins for a marketing site or a Next.js frontend.&lt;/p&gt;

&lt;p&gt;This guide ranks &lt;strong&gt;10 PaaS providers for web apps in 2026&lt;/strong&gt; , with &lt;a href="https://seenode.com/" rel="noopener noreferrer"&gt;seenode&lt;/a&gt; first: predictable fixed pricing, always-on services, managed databases, and a deploy-from-Git workflow that still feels like classic Heroku, without the surprise invoices.&lt;/p&gt;

&lt;p&gt;Pricing and features below are based on publicly available docs as of July 2026 and can change by region and plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Pick &lt;strong&gt;always-on PaaS&lt;/strong&gt; (seenode, Railway, Render, Fly.io, Heroku) when you need persistent processes, WebSockets, or workers, not only serverless functions.&lt;/li&gt;
&lt;li&gt;Pick &lt;strong&gt;frontend / edge PaaS&lt;/strong&gt; (Vercel, Netlify, Cloudflare Pages) when the app is mostly static or serverless and you want global CDN performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Billing model matters as much as features.&lt;/strong&gt; Fixed tiers (seenode, Render) beat usage metering if you hate surprise bills; usage-based (Railway, Fly.io) can win for bursty traffic.&lt;/li&gt;
&lt;li&gt;For a full stack under ~$15/month with a database, &lt;strong&gt;seenode&lt;/strong&gt; is usually the cheapest always-on option in this list.&lt;/li&gt;
&lt;li&gt;Hyperscaler-adjacent tools (DigitalOcean App Platform, AWS Amplify) shine when you already live in that ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Best for&lt;/th&gt;
&lt;th&gt;Pricing from*&lt;/th&gt;
&lt;th&gt;Billing&lt;/th&gt;
&lt;th&gt;Always-on&lt;/th&gt;
&lt;th&gt;Managed DB&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;seenode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Predictable cost full-stack apps&lt;/td&gt;
&lt;td&gt;From $3/mo&lt;/td&gt;
&lt;td&gt;Fixed tiers&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Postgres, MySQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Railway&lt;/td&gt;
&lt;td&gt;Heroku-like DX, variable traffic&lt;/td&gt;
&lt;td&gt;Free trial / usage&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Render&lt;/td&gt;
&lt;td&gt;Production defaults, teams&lt;/td&gt;
&lt;td&gt;Free tier / paid&lt;/td&gt;
&lt;td&gt;Fixed + usage&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Postgres, Redis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vercel&lt;/td&gt;
&lt;td&gt;Next.js and frontend apps&lt;/td&gt;
&lt;td&gt;Free / Pro ~$20/mo&lt;/td&gt;
&lt;td&gt;Seat + usage&lt;/td&gt;
&lt;td&gt;Serverless&lt;/td&gt;
&lt;td&gt;Via partners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DigitalOcean App Platform&lt;/td&gt;
&lt;td&gt;Hybrid PaaS + DO cloud&lt;/td&gt;
&lt;td&gt;Free / ~$5/mo&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fly.io&lt;/td&gt;
&lt;td&gt;Multi-region, low latency&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Optional managed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Heroku&lt;/td&gt;
&lt;td&gt;Mature classic PaaS&lt;/td&gt;
&lt;td&gt;~$7/mo dynos&lt;/td&gt;
&lt;td&gt;Dyno tiers&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Postgres + add-ons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Netlify&lt;/td&gt;
&lt;td&gt;JAMstack / Deploy Previews&lt;/td&gt;
&lt;td&gt;Free / ~$9-20/mo&lt;/td&gt;
&lt;td&gt;Seat + usage&lt;/td&gt;
&lt;td&gt;Serverless&lt;/td&gt;
&lt;td&gt;Via partners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS Amplify&lt;/td&gt;
&lt;td&gt;AWS-centric full-stack frontends&lt;/td&gt;
&lt;td&gt;Free tier / usage&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Mixed&lt;/td&gt;
&lt;td&gt;Via AWS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cloudflare Pages&lt;/td&gt;
&lt;td&gt;Edge speed, static + Workers&lt;/td&gt;
&lt;td&gt;Free / paid&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Edge&lt;/td&gt;
&lt;td&gt;Via partners&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;*Entry prices are approximate starting points for a small app; real stacks (web + DB + seats) usually cost more. See each section.&lt;/p&gt;

&lt;h2&gt;
  
  
  How we evaluated
&lt;/h2&gt;

&lt;p&gt;We scored platforms the way a small team actually chooses:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stack fit:&lt;/strong&gt; Can you run Python, Node.js, Go, or similar backends, not only static sites?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer experience:&lt;/strong&gt; Git deploys, logs, previews, dashboards without a dedicated DevOps person.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pricing predictability:&lt;/strong&gt; Fixed tiers vs metered CPU/egress vs per-seat plans.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Databases &amp;amp; workers:&lt;/strong&gt; Managed Postgres/MySQL, background workers, private networking.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Runtime model:&lt;/strong&gt; Always-on processes vs serverless/edge (cold starts, WebSockets, timeouts).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Support:&lt;/strong&gt; Docs quality and whether a human will help when a deploy breaks at 6pm.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a deeper look at billing models specifically, see our &lt;a href="https://seenode.com/blog/heroku-alternatives-decision-framework" rel="noopener noreferrer"&gt;Heroku alternatives decision framework&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. seenode: best for predictable, always-on web apps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fek9qubgkqcjcliyys6g5.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fek9qubgkqcjcliyys6g5.webp" alt="seenode homepage showing deploy-from-GitHub messaging" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://seenode.com/" rel="noopener noreferrer"&gt;seenode&lt;/a&gt; is a developer PaaS built for shipping web services, workers, and managed databases without becoming an infrastructure team. Connect GitHub or GitLab, pick a repo, and get a public URL with SSL. You can even start a deploy before creating an account, claim it when you are ready, with a 7-day free trial.&lt;/p&gt;

&lt;p&gt;seenode targets the gap left after Heroku’s free tier disappeared: &lt;strong&gt;always-on apps with Heroku-like simplicity and fixed monthly pricing&lt;/strong&gt;. No cold starts, no per-request metering, no per-seat fees. That makes it a strong default for side projects, MVPs, and small SaaS products that need a real backend plus Postgres or MySQL.&lt;/p&gt;

&lt;p&gt;Native runtimes include Python, Node.js, Go, and Elixir. You get centralized logs (7 days), private networking between services, zero-downtime deploys, horizontal or vertical scaling, and unlimited team members. Support is live chat with platform engineers, not a ticket black hole.&lt;/p&gt;

&lt;h3&gt;
  
  
  seenode key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Git-based deploys&lt;/strong&gt; from GitHub/GitLab with automatic builds and SSL URLs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero cold starts:&lt;/strong&gt; always-on processes for WebSockets, SSE, and persistent connections&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Managed PostgreSQL and MySQL&lt;/strong&gt; in the same project as your apps and workers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fixed monthly pricing&lt;/strong&gt; , charged daily, with no per-seat or per-request surprises&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unlimited team seats&lt;/strong&gt; and pair-debugging support from the people who build the platform&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  seenode pricing (as of July 2026)
&lt;/h3&gt;

&lt;p&gt;Pricing starts at &lt;strong&gt;$3/month&lt;/strong&gt; for a basic web service. A common starter stack with web + Postgres is often around &lt;strong&gt;$7 to $11/month&lt;/strong&gt; , depending on tier. Larger setups stay fixed-tier; seenode’s public comparison shows a 3-app + Postgres + storage stack at roughly &lt;strong&gt;$15.50/month&lt;/strong&gt; vs much higher on Render for a similar footprint. Explore current numbers on &lt;a href="https://seenode.com/pricing" rel="noopener noreferrer"&gt;seenode pricing&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Solo developers and small teams who want always-on apps, a database, and a bill they can predict.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You need multi-region edge by default or a huge add-on marketplace on day one.&lt;/p&gt;


&lt;p&gt;seenode&lt;/p&gt; &lt;h3&gt;Deploy your app on seenode&lt;/h3&gt; &lt;p&gt; Connect GitHub, pick a repo, and go live in minutes. No account or credit card required to start. 7-day free trial. &lt;a href="https://seenode.com/pricing?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
See pricing&lt;br&gt;
 &lt;/a&gt; &lt;/p&gt;   &lt;a href="https://seenode.com/deploy/github?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
Deploy from GitHub&lt;br&gt;
 &lt;/a&gt;  

&lt;h2&gt;
  
  
  2. Railway: best for Heroku-like workflows with usage billing
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5xjbqzno4k29i0lqoab.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo5xjbqzno4k29i0lqoab.webp" alt="Railway homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Railway is the platform many teams tried first after leaving Heroku. Deploy from Git, Docker, or the CLI; attach managed databases; use private networking between services. The DX is fast, and the product feels built for full-stack apps rather than marketing sites.&lt;/p&gt;

&lt;p&gt;The tradeoff is &lt;strong&gt;usage-based pricing&lt;/strong&gt;. Quiet apps can stay cheap; sustained traffic or chatty services can push the bill up quickly. That is fine if you watch usage, painful if you do not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Railway key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Git, Docker, and local deploy paths with rollbacks and observability&lt;/li&gt;
&lt;li&gt;Managed databases and persistent volumes&lt;/li&gt;
&lt;li&gt;Private networking and TCP proxies&lt;/li&gt;
&lt;li&gt;Unlimited preview environments on higher plans&lt;/li&gt;
&lt;li&gt;Usage-based Hobby and Pro tiers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Railway pricing
&lt;/h3&gt;

&lt;p&gt;Hobby includes a small usage credit; Pro is commonly around &lt;strong&gt;$20/month&lt;/strong&gt; with included credit, and real production apps often land in the &lt;strong&gt;$20-30+/month&lt;/strong&gt; range depending on CPU, memory, and egress.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Variable traffic and teams that like Railway’s project model.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You need a fixed invoice every month.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Render: best for production-ready defaults
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F52babx8ccg7pup44ynyi.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F52babx8ccg7pup44ynyi.webp" alt="Render homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Render is a unified cloud for web services, static sites, background workers, cron jobs, and managed Postgres/Redis. Git auto-deploys, zero-downtime releases, and private networking make it a common “boring production” choice for agencies and startups.&lt;/p&gt;

&lt;p&gt;Pricing is more expensive than seenode for comparable always-on stacks, especially once you add Postgres with production features and a paid workspace. You pay for stability and a mature feature set.&lt;/p&gt;

&lt;h3&gt;
  
  
  Render key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Automatic Git deploys and Docker support&lt;/li&gt;
&lt;li&gt;Native workers, cron jobs, and preview environments&lt;/li&gt;
&lt;li&gt;Managed PostgreSQL and Redis with private networking&lt;/li&gt;
&lt;li&gt;Infrastructure as Code via &lt;code&gt;render.yaml&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;DDoS protection and zero-downtime deploys&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Render pricing
&lt;/h3&gt;

&lt;p&gt;Free tiers exist for experiments; production web + Postgres setups often start in the &lt;strong&gt;tens of dollars per month&lt;/strong&gt; and climb with PITR, larger DBs, and team plans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Client work and teams that want opinionated production defaults.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; Budget is under ~$15/month for web + database.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Vercel: best for Next.js and frontend-centric apps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwxkr185d8for2garr4kz.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwxkr185d8for2garr4kz.webp" alt="Vercel homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vercel owns the Next.js deployment experience: Git integration, preview deployments per PR, and a global edge network. Serverless and edge functions cover APIs, but the platform is optimized for frontend and JAMstack patterns, not long-running backends.&lt;/p&gt;

&lt;p&gt;If your “web app” is mostly React/Next with serverless APIs, Vercel is excellent. If you need always-on workers, WebSockets, or a traditional app server, look at seenode, Railway, Render, or Fly.io instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First-class Next.js and modern frontend frameworks&lt;/li&gt;
&lt;li&gt;Preview deployments and team collaboration controls&lt;/li&gt;
&lt;li&gt;Edge network, serverless functions, and AI SDK tooling&lt;/li&gt;
&lt;li&gt;Integrated storage options (Blob and related services)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Vercel pricing
&lt;/h3&gt;

&lt;p&gt;Generous free hobby tier; &lt;strong&gt;Pro from about $20/month&lt;/strong&gt; per seat, plus usage for functions and bandwidth on heavier apps.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Next.js products and frontend teams.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You need persistent servers, workers, or cheap always-on Postgres next to the app.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. DigitalOcean App Platform: best for hybrid PaaS + cloud
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe3b68sfmi0yjwdib498.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbe3b68sfmi0yjwdib498.webp" alt="DigitalOcean App Platform" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DigitalOcean App Platform sits on top of DigitalOcean’s broader cloud: deploy from Git or containers, mix services/workers/static sites, and grow into Droplets, managed databases, or GPU/AI products when you need them.&lt;/p&gt;

&lt;p&gt;It is a solid middle ground when you want PaaS simplicity with an escape hatch into classic cloud infrastructure, without jumping straight to AWS complexity.&lt;/p&gt;

&lt;h3&gt;
  
  
  DigitalOcean App Platform key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Git-based deploys with component architecture (services, workers, static sites)&lt;/li&gt;
&lt;li&gt;Built-in HTTPS, CDN, and app-level logs&lt;/li&gt;
&lt;li&gt;Vertical and component-level scaling&lt;/li&gt;
&lt;li&gt;Path into Droplets, managed DBs, and AI/GPU products&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DigitalOcean pricing
&lt;/h3&gt;

&lt;p&gt;Static/free tiers for light apps; paid App Platform plans commonly start around &lt;strong&gt;$5/month&lt;/strong&gt; , with costs rising as you add dedicated CPU and databases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams that want managed deploys plus optional DO infrastructure.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You only need a tiny always-on API and want the absolute lowest fixed bill.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Fly.io: best for multi-region and proximity to users
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx9mzwbwzhilbz7nytnv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx9mzwbwzhilbz7nytnv.webp" alt="Fly.io homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fly.io runs full containers close to users across many regions. That is powerful for latency-sensitive apps and global products. Machines can scale to zero, which helps cost, but managed Postgres and always-on capacity change the economics fast.&lt;/p&gt;

&lt;p&gt;Expect a steeper learning curve than seenode or Railway. The payoff is control over where your app runs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fly.io key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Global regions and Anycast networking&lt;/li&gt;
&lt;li&gt;Full Docker/OCI workloads with scaling options&lt;/li&gt;
&lt;li&gt;Optional managed Postgres (watch the price jump)&lt;/li&gt;
&lt;li&gt;Strong fit for latency-sensitive APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Fly.io pricing
&lt;/h3&gt;

&lt;p&gt;Usage-based compute can look cheap for idle hobby apps ( &lt;strong&gt;often under $15/month&lt;/strong&gt; without managed Postgres). Adding managed Postgres frequently pushes totals toward &lt;strong&gt;~$45-50/month&lt;/strong&gt; , a cliff many comparison posts underplay.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Multi-region and performance-sensitive workloads.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You want the simplest dashboard and a flat invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Heroku: best for mature, classic PaaS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feqxcnl7q65ehyakwb7hy.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feqxcnl7q65ehyakwb7hy.webp" alt="Heroku homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Heroku invented the dyno mental model many of us still use. Buildpacks, add-ons, review apps, and a huge ecosystem remain useful. The platform is stable and familiar, but innovation is slower, and pricing is rarely the cheapest option for a small always-on stack.&lt;/p&gt;

&lt;p&gt;Still a valid choice if your team already knows Heroku or depends on specific add-ons.&lt;/p&gt;

&lt;h3&gt;
  
  
  Heroku key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Dyno-based scaling and Cloud Native Buildpacks&lt;/li&gt;
&lt;li&gt;Large add-on marketplace (data, monitoring, messaging)&lt;/li&gt;
&lt;li&gt;Private Spaces and compliance-oriented offerings&lt;/li&gt;
&lt;li&gt;Mature CLI and developer workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Heroku pricing
&lt;/h3&gt;

&lt;p&gt;Basic dynos often start around &lt;strong&gt;$7/month&lt;/strong&gt; , with Postgres and add-ons stacking quickly for production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams standardized on Heroku’s ecosystem.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You are cost-sensitive or want the newest PaaS DX.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Netlify: best for JAMstack and Deploy Previews
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frf3opqx2kdqhdipyf9m0.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frf3opqx2kdqhdipyf9m0.webp" alt="Netlify homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Netlify popularized Deploy Previews and a polished JAMstack workflow. Global CDN, serverless/edge functions, forms, and identity features make it strong for content sites and frontend apps, not a replacement for a classic always-on API host.&lt;/p&gt;

&lt;h3&gt;
  
  
  Netlify key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Deploy Previews tied to pull requests&lt;/li&gt;
&lt;li&gt;Serverless and edge functions&lt;/li&gt;
&lt;li&gt;Global CDN and build tooling&lt;/li&gt;
&lt;li&gt;Identity and forms on higher plans&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Netlify pricing
&lt;/h3&gt;

&lt;p&gt;Free personal tier; paid plans commonly from about &lt;strong&gt;$9-20/user/month&lt;/strong&gt; plus usage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Marketing sites, docs, and frontend-heavy products.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; Your core product is a long-running backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. AWS Amplify: best for AWS-centric frontends
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F422dw8r2m8tyytwf6y5n.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F422dw8r2m8tyytwf6y5n.webp" alt="AWS Amplify homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS Amplify helps frontend teams deploy apps and wire into Cognito, AppSync, S3, and the rest of AWS. Pull request previews and Amplify Hosting are convenient if you already live in Amazon’s ecosystem.&lt;/p&gt;

&lt;p&gt;The downside is classic AWS: powerful, but complexity and cost visibility can grow quickly once you leave the happy path.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Amplify key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Hosting with PR previews&lt;/li&gt;
&lt;li&gt;Auth, storage, and API integrations with AWS services&lt;/li&gt;
&lt;li&gt;Amplify Studio and CLI for backend wiring&lt;/li&gt;
&lt;li&gt;Fits teams already standardized on AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  AWS Amplify pricing
&lt;/h3&gt;

&lt;p&gt;Pay for Amplify Hosting and underlying AWS resources. Entry can look cheap; production AWS bills need monitoring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Frontend apps that must plug into AWS deeply.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You want a simple Heroku-style PaaS with one predictable invoice.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Cloudflare Pages: best for edge speed and static-first apps
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9aszwv9h43iu1m6bb8r.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo9aszwv9h43iu1m6bb8r.webp" alt="Cloudflare Pages homepage" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cloudflare Pages deploys sites and JAMstack apps onto Cloudflare’s global network, with Pages Functions (Workers) for dynamic behavior at the edge. Unlimited bandwidth on Pages plans is a real advantage for traffic spikes.&lt;/p&gt;

&lt;p&gt;Like Vercel and Netlify, it is not the first pick for traditional always-on app servers, but for edge-first architectures it is hard to beat on latency and CDN reach.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloudflare Pages key features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Git-integrated continuous deployment&lt;/li&gt;
&lt;li&gt;Pages Functions on the edge network&lt;/li&gt;
&lt;li&gt;Global CDN performance and DDoS posture&lt;/li&gt;
&lt;li&gt;Unmetered bandwidth on Pages plans&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cloudflare pricing
&lt;/h3&gt;

&lt;p&gt;Generous free tier; paid Workers/Pages plans for heavier compute and team features.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Static and edge-rendered apps that need global speed.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Skip if:&lt;/strong&gt; You need a classic always-on Node/Python process next to managed Postgres in one dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to choose the right PaaS
&lt;/h2&gt;

&lt;p&gt;Use this shortcut:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Side project or MVP under $15/month with a database&lt;/strong&gt; → &lt;strong&gt;seenode&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Heroku-like DX and you accept usage bills&lt;/strong&gt; → &lt;strong&gt;Railway&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agency / client production defaults&lt;/strong&gt; → &lt;strong&gt;Render&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next.js-first product&lt;/strong&gt; → &lt;strong&gt;Vercel&lt;/strong&gt; (pair a backend PaaS if you outgrow serverless)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Already on DigitalOcean&lt;/strong&gt; → &lt;strong&gt;App Platform&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need many regions&lt;/strong&gt; → &lt;strong&gt;Fly.io&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend/edge only&lt;/strong&gt; → &lt;strong&gt;Netlify&lt;/strong&gt; or &lt;strong&gt;Cloudflare Pages&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep AWS integration&lt;/strong&gt; → &lt;strong&gt;Amplify&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If billing model is the deciding factor, read the full breakdown in &lt;a href="https://seenode.com/blog/heroku-alternatives-decision-framework" rel="noopener noreferrer"&gt;Heroku Alternatives Decision Framework&lt;/a&gt;.&lt;/p&gt;


&lt;p&gt;seenode&lt;/p&gt; &lt;h3&gt;Still deciding? Deploy a real repo&lt;/h3&gt; &lt;p&gt; Compare seenode to Railway or Render with the same app. No credit card required to start. 7-day free trial. &lt;a href="https://seenode.com/pricing?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
See pricing&lt;br&gt;
 &lt;/a&gt; &lt;/p&gt;   &lt;a href="https://seenode.com/deploy/github?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
Deploy from GitHub&lt;br&gt;
 &lt;/a&gt;  

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is the best PaaS for a large-scale web app?
&lt;/h3&gt;

&lt;p&gt;For large scale, prioritize autoscaling, observability, and operational maturity. &lt;strong&gt;Render&lt;/strong&gt; , &lt;strong&gt;Fly.io&lt;/strong&gt; , and hyperscaler-adjacent platforms (DigitalOcean, AWS) are common choices. Many teams still start on a simpler always-on PaaS like &lt;strong&gt;seenode&lt;/strong&gt; or &lt;strong&gt;Railway&lt;/strong&gt; , then split services or move parts of the stack when traffic justifies it. Pure VPS/IaaS wins only when you need OS-level control that PaaS will not give you.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is PaaS better than VPS hosting for web apps?
&lt;/h3&gt;

&lt;p&gt;For most product teams, yes. PaaS is faster to ship and cheaper in engineering time. Choose a VPS when you need custom kernels, unusual networking, or specialized software that no PaaS supports. Do not pick a VPS just to “save money” unless you enjoy being on-call for patching and SSL renewals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which PaaS is best if I am leaving Heroku?
&lt;/h3&gt;

&lt;p&gt;Closest workflow: &lt;strong&gt;Railway&lt;/strong&gt;. Closest economics for a small always-on app + database: &lt;strong&gt;seenode&lt;/strong&gt;. Closest “enterprise boring”: &lt;strong&gt;Render&lt;/strong&gt;. Details and cost tables: &lt;a href="https://seenode.com/blog/heroku-alternatives-decision-framework" rel="noopener noreferrer"&gt;Heroku alternatives decision framework&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I host a full-stack app with a database on these platforms?
&lt;/h3&gt;

&lt;p&gt;Yes on &lt;strong&gt;seenode&lt;/strong&gt; , &lt;strong&gt;Railway&lt;/strong&gt; , &lt;strong&gt;Render&lt;/strong&gt; , &lt;strong&gt;DigitalOcean&lt;/strong&gt; , &lt;strong&gt;Fly.io&lt;/strong&gt; , and &lt;strong&gt;Heroku&lt;/strong&gt;. On &lt;strong&gt;Vercel&lt;/strong&gt; , &lt;strong&gt;Netlify&lt;/strong&gt; , &lt;strong&gt;Amplify&lt;/strong&gt; , and &lt;strong&gt;Cloudflare Pages&lt;/strong&gt; , you typically attach an external database (Neon, PlanetScale, Supabase, RDS, etc.) and keep the host focused on frontend/serverless.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I migrate to seenode?
&lt;/h3&gt;

&lt;p&gt;Point a GitHub or GitLab repo at seenode, set build/start commands and env vars, provision Postgres or MySQL if needed, and deploy. Start from the &lt;a href="https://seenode.com/docs" rel="noopener noreferrer"&gt;seenode docs&lt;/a&gt; or just &lt;a href="https://seenode.com/deploy/github" rel="noopener noreferrer"&gt;deploy from GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ship your web app without the infrastructure tax
&lt;/h2&gt;

&lt;p&gt;If you want always-on web services, workers, and managed databases with &lt;strong&gt;fixed pricing and no per-seat fees&lt;/strong&gt; , seenode is built for that: predictable invoices, no per-seat fees, and a deploy loop that gets out of your way.&lt;/p&gt;


&lt;p&gt;seenode&lt;/p&gt; &lt;h3&gt;Ship your web app on seenode&lt;/h3&gt; &lt;p&gt; Deploy from GitHub in minutes. Claim the account when you are ready. Keep the invoice predictable as you grow. &lt;a href="https://seenode.com/pricing?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
See pricing&lt;br&gt;
 &lt;/a&gt; &lt;/p&gt;   &lt;a href="https://seenode.com/deploy/github?utm_source=blog&amp;amp;utm_medium=cta&amp;amp;utm_campaign=best-paas-2026" rel="noopener noreferrer"&gt; &lt;br&gt;
Deploy from GitHub&lt;br&gt;
 &lt;/a&gt;  

</description>
      <category>paas</category>
      <category>hosting</category>
      <category>deployment</category>
      <category>webapps</category>
    </item>
    <item>
      <title>How to Try Egonex ECP in .NET 8 and Send Emergency Alerts with an 8-Byte Payload</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Wed, 15 Apr 2026 22:52:39 +0000</pubDate>
      <link>https://dev.to/geosegun/how-to-try-egonex-ecp-in-net-8-and-send-emergency-alerts-with-an-8-byte-payload-185p</link>
      <guid>https://dev.to/geosegun/how-to-try-egonex-ecp-in-net-8-and-send-emergency-alerts-with-an-8-byte-payload-185p</guid>
      <description>&lt;p&gt;&lt;strong&gt;Disclosure:&lt;/strong&gt; I was asked by the ECP team to evaluate their SDK and write an honest review. All opinions are my own.&lt;/p&gt;

&lt;p&gt;Emergency alerts are usually discussed in terms of speed, reach, and reliability. But there is another variable underneath all of that that matters just as much in practice: how much data the system has to move to describe the alert in the first place.&lt;/p&gt;

&lt;p&gt;That is part of what makes ECP, short for Emergency Communication Protocol, interesting. In the default ProofCard run, the sample produces 669 bytes in CAP XML, 270 bytes in JSON, and just 8 bytes in ECP’s UET format. When modified to the earthquake scenario used in this walkthrough, the output becomes 686 bytes in CAP XML, 279 bytes in JSON, and still 8 bytes in ECP UET. The project also reports an average 96 percent data reduction. Those numbers are striking enough that they deserve more than a quick skim of a README.&lt;/p&gt;

&lt;p&gt;They are also interesting for reasons beyond a neat benchmark. In emergency systems, smaller payloads can matter when alerts need to move across constrained or failure-prone links, and many public-warning delivery channels still impose practical size or formatting constraints on what can be transmitted. For low-bandwidth deployments or any workflow where overhead matters, the difference between a few hundred bytes and a single-digit payload is not just cosmetic. It can shape how efficiently a message is encoded, transmitted, retried, and inspected.&lt;/p&gt;

&lt;p&gt;This article walks through the practical side of that claim using the open-source .NET 8 SDK. The goal is simple: clone the &lt;a href="https://github.com/Egonex-Code/ecp-protocol" rel="noopener noreferrer"&gt;repository&lt;/a&gt;, get the environment working, run the tests, execute the samples, modify one of them, generate a real payload, and then verify the result in &lt;a href="https://egonex-code.github.io/ecp-protocol/studio/" rel="noopener noreferrer"&gt;ECP Studio&lt;/a&gt;. By the end, the point is not just to repeat that ECP is compact, but to see what the workflow actually looks like when the SDK is run locally and the output is validated step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting set up
&lt;/h2&gt;

&lt;p&gt;The setup path is straightforward on paper. The repository can be cloned, restored, and tested through the normal .NET CLI flow, which makes this feel familiar if you have worked through a standard .NET repository before.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/Egonex-Code/ecp-protocol.git
&lt;span class="nb"&gt;cd &lt;/span&gt;ecp-protocol
dotnet restore
dotnet &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There was, however, one environment issue worth mentioning because it is the kind of thing that can derail a hands-on review early. In the local run, &lt;code&gt;dotnet test&lt;/code&gt; initially failed with a missing &lt;code&gt;Microsoft.NETCore.App&lt;/code&gt; 8.0.6 message because the machine only had .NET 10 installed while the solution targeted &lt;code&gt;net8.0&lt;/code&gt;. Installing the .NET 8 SDK resolved the version gap, but the shell was still resolving &lt;code&gt;dotnet&lt;/code&gt; to an older local install under &lt;code&gt;.dotnet&lt;/code&gt;, so the PATH had to be corrected before the CLI started returning an 8.0.4xx build.&lt;/p&gt;

&lt;p&gt;Once the environment pointed at the right SDK, the rest of the process snapped into place. The repository restored successfully, and the full test run passed across the solution, which is exactly the kind of baseline confirmation worth getting before drawing any conclusions about the SDK itself. That also helped separate an environment problem from a repo problem, which is always useful when writing about a developer workflow.&lt;/p&gt;

&lt;p&gt;Since this run, the repository added a &lt;code&gt;global.json&lt;/code&gt; pin with &lt;code&gt;rollForward: latestFeature&lt;/code&gt; (released in v2.0.6), so new clones should not run into the same SDK resolution issue.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfeglrsiosbszd32t0sd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frfeglrsiosbszd32t0sd.png" alt="dotnet test passing on net8.0" width="800" height="311"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: Full &lt;code&gt;dotnet test&lt;/code&gt; run on &lt;code&gt;net8.0&lt;/code&gt; passing across the ECP solution.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Running the samples
&lt;/h2&gt;

&lt;p&gt;The best place to start after setup is the &lt;code&gt;ProofCard&lt;/code&gt; sample because it makes the central claim visible almost immediately. In the default run, the sample output shows CAP XML at 669 bytes, JSON at 270 bytes, and ECP UET at 8 bytes. In the modified earthquake run from this walkthrough, the output is CAP XML at 686 bytes, JSON at 279 bytes, and ECP UET still at 8 bytes.&lt;/p&gt;

&lt;p&gt;That is the moment where the protocol starts to feel concrete. It is one thing to read that a format is compact; it is another to run a sample and see the same alert represented across multiple encodings with the byte counts sitting side by side in the console. The &lt;code&gt;ProofCard&lt;/code&gt; sample works well because it does not bury the value proposition in pages of explanation. It just shows the numbers and lets them do most of the work.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm989l1s2uytwckv4acv.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm989l1s2uytwckv4acv.webp" alt="ProofCard fire scenario output" width="800" height="385"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: ProofCard size comparison output showing CAP XML vs JSON vs ECP UET.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpubf6diyc4xv9dnpjss8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpubf6diyc4xv9dnpjss8.png" alt="Fire Scenario Byte Comparison" width="799" height="571"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: Byte comparison chart for the Fire scenario (CAP XML 669, JSON 270, ECP UET 8).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;To make the exercise more than a copy-and-run test, the next step was to change the scenario. The local notes modified the sample from a fire scenario to an earthquake scenario, updated the zone hash to 2002, and switched the alert call to &lt;code&gt;EmergencyType.Earthquake&lt;/code&gt;. That change produced output identifying the scenario as &lt;code&gt;EARTHQUAKE / Zone 12&lt;/code&gt;, along with a new proof hash and a generated payload, which made the sample feel like an actual SDK surface rather than a fixed demo.&lt;/p&gt;

&lt;p&gt;A simplified version of the alert call looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;alert&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Ecp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;EmergencyType&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Earthquake&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;zoneHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2002&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EcpPriority&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Critical&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timestampMinutes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;12345&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is one of the more encouraging parts of the SDK experience. At the level tested here, the API surface for a basic alert does not feel huge, and the changes needed to move from the default scenario to a custom one are small enough to follow without getting lost in abstraction.&lt;/p&gt;

&lt;p&gt;Another sample worth checking is the signed-envelope round-trip flow. In the local walkthrough, that sample generated an HMAC key, encoded an envelope, and then attempted validation with both the correct key and the wrong one. The wrong-key path returned &lt;code&gt;IsValid False&lt;/code&gt;, which is a compact but effective demonstration of validation and tamper detection behavior.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rvdmllc2ysb59pl1lsx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rvdmllc2ysb59pl1lsx.png" alt="Envelope signed roundtrip validation output" width="800" height="358"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: &lt;code&gt;ECP.Sample.Minimal&lt;/code&gt; plus &lt;code&gt;02-EnvelopeSignedRoundtrip&lt;/code&gt;, including wrong-key verification failure (&lt;code&gt;IsValid: False&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaojmx3igwu7kqot0va9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaojmx3igwu7kqot0va9.png" alt="Signed Envelope Validation Flow" width="733" height="858"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: Signed-envelope decode flow showing valid-key success and wrong-key failure.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Verifying in Studio
&lt;/h2&gt;

&lt;p&gt;The most satisfying part of the process came after generating a real payload locally. Running the modified sample with payload output enabled produced the UET hex value &lt;code&gt;2C001F48C0E40000&lt;/code&gt;, which then became the input for the browser-side verification step.&lt;/p&gt;

&lt;p&gt;Pasting that value into &lt;a href="https://egonex-code.github.io/ecp-protocol/studio/" rel="noopener noreferrer"&gt;ECP Studio’s Decode tab&lt;/a&gt; parsed it back into the same fields used in the sample, including &lt;code&gt;EmergencyType: Earthquake&lt;/code&gt;, &lt;code&gt;Priority: Critical&lt;/code&gt;, &lt;code&gt;ZoneHash: 2002&lt;/code&gt;, and &lt;code&gt;TimestampMinutes: 12345&lt;/code&gt;. That round-trip is what ties the whole workflow together. The code generates the bytes, the browser tool decodes them, and the fields line up without needing an extra helper script or custom parser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsouw9sv07srhgnpsbvyf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsouw9sv07srhgnpsbvyf.png" alt="ProofCard show-payload output" width="800" height="245"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: &lt;code&gt;dotnet run -- --show-payload&lt;/code&gt; output, including CAP, JSON, and UET hex (&lt;code&gt;2C001F48C0E40000&lt;/code&gt;).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7hh06lp902tbo56acuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7hh06lp902tbo56acuh.png" alt="ECP Studio decode screenshot" width="800" height="629"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Figure: ECP Studio Decode tab parsing &lt;code&gt;2C001F48C0E40000&lt;/code&gt; into Earthquake/Critical/ZoneHash 2002/TimestampMinutes 12345.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Studio also helps with the part of the protocol that is harder to communicate through prose alone: comparison. The local notes mention using the Compare tab to make the size differences easier to grasp visually as scenarios change, which gives the browser tool a real role beyond simple decoding. It becomes a practical companion to the SDK rather than just a nice extra.&lt;/p&gt;

&lt;p&gt;This is also where the broader implication of the compact payload starts to click. If a machine-readable emergency alert can be represented in 8 bytes for its core form while equivalent CAP XML and JSON representations are measured in the hundreds of bytes in the same sample, that can matter in emergency systems, low-bandwidth environments, and any workflow where message overhead competes with transport constraints or reliability goals. Even when the surrounding system still needs richer metadata, logs, signatures, or interoperability layers, reducing the size of the core alert token can change the shape of the transmission problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What stands out
&lt;/h2&gt;

&lt;p&gt;What stands out most after running through the SDK is not that the repository is unusually complex. It is that the path from install to validation is fairly short once the machine is pointing at the correct .NET 8 environment. The repository tests provide a clear baseline, the &lt;code&gt;ProofCard&lt;/code&gt; sample shows the size difference immediately, the scenario changes are easy to follow, and Studio closes the loop by decoding the locally generated payload back into readable fields.&lt;/p&gt;

&lt;p&gt;That is what makes the 8-byte claim more interesting than a headline. In this case, it was not just a number in project copy or a benchmark repeated from a README; it was something that could be reproduced locally, inspected in the console, modified through a small code change, and verified through the project’s own browser tooling.&lt;/p&gt;

&lt;p&gt;For developers working near emergency communications, constrained networks, or systems where payload size affects efficiency, the practical takeaway is straightforward. ECP becomes much easier to evaluate once it moves from an abstract compression claim to a concrete engineering workflow: clone the repo, run the SDK, generate the alert, and verify the bytes yourself. And that is really the point of a hands-on review like this one: not just to admire the 8-byte number, but to test whether the path from idea to validation is real. Developers who want to work with the encoder and decoder directly can start with the ECP.Core package on NuGet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub repository: &lt;a href="https://github.com/Egonex-Code/ecp-protocol" rel="noopener noreferrer"&gt;Egonex-Code/ecp-protocol&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;NuGet package: &lt;a href="https://www.nuget.org/packages/ECP.Core" rel="noopener noreferrer"&gt;ECP.Core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;ECP Studio: &lt;a href="https://egonex-code.github.io/ecp-protocol/studio/" rel="noopener noreferrer"&gt;egonex-code.github.io/ecp-protocol/studio/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Wire format specification: &lt;a href="https://github.com/Egonex-Code/ecp-protocol/blob/main/docs/specification/wire-format.md" rel="noopener noreferrer"&gt;docs/specification/wire-format.md&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>emergency</category>
      <category>dotnet</category>
      <category>iot</category>
    </item>
    <item>
      <title>Why Your Developer Tutorials Aren't Converting and How to Fix Them</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Sun, 15 Mar 2026 00:00:00 +0000</pubDate>
      <link>https://dev.to/geosegun/why-your-developer-tutorials-arent-converting-and-how-to-fix-them-2ae1</link>
      <guid>https://dev.to/geosegun/why-your-developer-tutorials-arent-converting-and-how-to-fix-them-2ae1</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrz2u012yrwvlpi3yvjj.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxrz2u012yrwvlpi3yvjj.webp" alt="Why Your Developer Tutorials Aren't Converting and How to Fix Them" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Developer tutorials fail to convert because they delay the first working result and focus too much on explanation instead of execution&lt;/li&gt;
&lt;li&gt;Conversion in devtools happens when a developer gets something working, not when they understand the product&lt;/li&gt;
&lt;li&gt;High-converting tutorials optimize for Time to First Success (TTFS) with clear outcomes, minimal setup, and runnable examples&lt;/li&gt;
&lt;li&gt;The best tutorials guide developers to a quick win, reduce friction, and are continuously improved based on real usage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A developer comes to your tutorial with a specific goal in mind. They want to try your product and get something working quickly. A few steps in, they are still setting things up, reading through explanations, and trying to make sense of everything. There is no clear result yet, no small win to confirm they are on the right path. After a while, they give up and leave. This is where most tutorials fail. Not because they are wrong, but because they do not lead to a quick win.&lt;/p&gt;

&lt;p&gt;This article breaks down why developer tutorials do not convert and how to fix them. It explores where most tutorials go wrong, what high-converting tutorials do differently, and how to design tutorials that guide developers from first interaction to real success.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer tutorials are your real conversion funnel
&lt;/h2&gt;

&lt;p&gt;In devtools, conversion does not happen at signup. It happens when a developer gets something working.&lt;/p&gt;

&lt;p&gt;A developer can create an account, read your docs, and still leave without ever using your product. What changes that is a working result. The moment they make a successful API call, see data returned, or complete a small task, that is when your product starts to make sense.&lt;/p&gt;

&lt;p&gt;This is why tutorials matter more than most teams think. Documentation helps developers understand your product, but tutorials are what help them experience it. They are the bridge between interest and actual usage.&lt;/p&gt;

&lt;p&gt;You can think of it simply. Documentation supports onboarding. Tutorials create the first success. That first success drives adoption.&lt;/p&gt;

&lt;p&gt;If your tutorial does not get a developer to a working outcome quickly, your product never gets a fair chance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where most developer tutorials break down
&lt;/h2&gt;

&lt;p&gt;Most developer tutorials look complete, but they fail where it matters. They do not help developers get to a working outcome fast enough. The result is content that seems useful but does not move the developer forward in the moment it counts.&lt;/p&gt;

&lt;p&gt;Here are the most common points where developer tutorials break down:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;No clear outcome&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Many tutorials start with vague goals like “build something” or “get started.” The problem is that the developer does not know what success looks like.&lt;/p&gt;

&lt;p&gt;Compare this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build a sample app vs&lt;/li&gt;
&lt;li&gt;Create a working API request that returns user data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The second gives a clear destination. The first leaves the developer guessing.&lt;/p&gt;

&lt;p&gt;A good tutorial defines the exact outcome upfront. If a developer cannot picture what they will achieve, they are less likely to stay.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Time to first success is too long&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is one of the biggest reasons tutorials fail.&lt;/p&gt;

&lt;p&gt;Before a developer sees any result, they are asked to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install multiple dependencies&lt;/li&gt;
&lt;li&gt;configure environments&lt;/li&gt;
&lt;li&gt;understand several concepts at once&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By the time they reach anything meaningful, they are already fatigued.&lt;/p&gt;

&lt;p&gt;This is where the idea of &lt;a href="https://www.cloudblue.com/glossary/time-to-first-sale-ttfs/" rel="noopener noreferrer"&gt;Time to First Success (TTFS)&lt;/a&gt; becomes important.&lt;/p&gt;

&lt;p&gt;TTFS is how long it takes for a developer to get something working for the first time. The longer it takes to reach that first working result, the more likely the developer is to drop off. High-converting tutorials reduce this time aggressively.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Tutorials explain instead of execute&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some tutorials read like documentation pages. They explain how the system works in detail, but delay actual execution.&lt;/p&gt;

&lt;p&gt;Developers are not looking for a deep explanation at the start. They want to take action.&lt;/p&gt;

&lt;p&gt;When tutorials lead with long explanations instead of a working step, they slow down progress. Explanation should support action, not replace it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Examples don’t actually work&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Nothing breaks trust faster than a tutorial that does not produce the expected result.&lt;/p&gt;

&lt;p&gt;Common issues include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing steps or assumptions&lt;/li&gt;
&lt;li&gt;outdated versions or dependencies&lt;/li&gt;
&lt;li&gt;unclear configuration requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a developer follows your tutorial and it does not work, they will assume the product is unreliable.&lt;/p&gt;

&lt;p&gt;This is where strong documentation practices matter. Examples should be complete, runnable, and validated, just like in high-quality &lt;a href="https://reclear.io/blog/developer-documentation-that-gets-used" rel="noopener noreferrer"&gt;developer documentation that gets used&lt;/a&gt;. The same principle applies even more strongly to tutorials.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Not tied to a real use case&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Some tutorials are technically correct but feel disconnected from real-world problems.&lt;/p&gt;

&lt;p&gt;They demonstrate features in isolation without answering a practical question like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;why would I use this&lt;/li&gt;
&lt;li&gt;when would I need this&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Developers want to solve real problems. Tutorials that are not grounded in actual use cases feel disconnected from real-world problems and are easier to abandon.&lt;/p&gt;

&lt;p&gt;Most developer tutorials fail not because they are wrong, but because they do not help developers move forward fast enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  The aha moment: developers don’t convert when they understand, they convert when they succeed
&lt;/h2&gt;

&lt;p&gt;It is easy to assume that developers convert when they understand your product. That's if your tutorial explains things clearly enough, they will see the value and continue.&lt;/p&gt;

&lt;p&gt;In reality, understanding is not what drives adoption. Execution is.&lt;/p&gt;

&lt;p&gt;A developer can read your documentation, follow your architecture, and still leave without using your product. But the moment they get something working, even something small, the experience changes. The product stops being abstract and starts becoming useful.&lt;/p&gt;

&lt;p&gt;This is the shift most teams miss.&lt;/p&gt;

&lt;p&gt;A developer who understands your product might still leave. A developer who gets something working will come back.&lt;/p&gt;

&lt;p&gt;This is why tutorials matter so much. They are not just educational content. They are the first real interaction a developer has with your product.&lt;/p&gt;

&lt;p&gt;If that interaction leads to success, you build confidence. If it leads to friction, you lose momentum.&lt;/p&gt;

&lt;p&gt;Everything about your tutorial should be designed around this idea. Not how much you can explain, but how quickly you can help a developer succeed.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to fix your developer tutorials (practical system)
&lt;/h2&gt;

&lt;p&gt;Once you understand where developer tutorials fail and what actually drives conversion, the next step is fixing them. This is not about rewriting everything. It is about restructuring your tutorials around how developers make progress.&lt;/p&gt;

&lt;p&gt;Start by being explicit about what the developer will achieve.&lt;/p&gt;

&lt;p&gt;Avoid vague goals like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Build a sample app”&lt;/li&gt;
&lt;li&gt;“Get started with the API”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead, define a clear, concrete result:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Create a user via the API and return a successful response”&lt;/li&gt;
&lt;li&gt;“Upload a file and retrieve its URL”&lt;/li&gt;
&lt;li&gt;“Authenticate a user and receive a valid token”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A strong developer tutorial answers this immediately: What will I have working at the end of this?&lt;/p&gt;
&lt;p&gt;You can make this even clearer by showing the expected output upfront.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  "id": "user_123",
  "email": "user@example.com"
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Most developer tutorials lose users before they even begin.&lt;/p&gt;
&lt;p&gt;Too many tutorials start with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;environment setup&lt;/li&gt;
&lt;li&gt;dependency installation&lt;/li&gt;
&lt;li&gt;configuration steps&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Before any value is shown.&lt;/p&gt;
&lt;p&gt;Every extra step before the first success increases drop-off. Your goal is to reduce setup to only what is absolutely required. Instead of:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;installing multiple tools&lt;/li&gt;
&lt;li&gt;configuring environments manually&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should consider:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;providing a pre-configured example&lt;/li&gt;
&lt;li&gt;using simple tools like curl or a single SDK&lt;/li&gt;
&lt;li&gt;deferring advanced setup to later sections&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For example, instead of asking a developer to install a full SDK, start with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl -X GET https://api.example.com/v1/users \
  -H "Authorization: Bearer YOUR_API_KEY"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This gets them to a working result faster. That is what matters.&lt;/p&gt;
&lt;p&gt;Before writing explanations, make sure the tutorial works end-to-end.&lt;/p&gt;

&lt;p&gt;This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;every step is tested&lt;/li&gt;
&lt;li&gt;every command runs&lt;/li&gt;
&lt;li&gt;every response is valid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not write the tutorial as you build the product. Write it after you have a working flow.&lt;/p&gt;

&lt;p&gt;A simple rule: If you copy your own tutorial and it fails, the tutorial is not ready.&lt;/p&gt;
&lt;p&gt;For example, instead of:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;POST /v1/users
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;You should write the full, runnable version:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;curl -X POST https://api.example.com/v1/users \
  -H "Authorization: Bearer sk_test_123456" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This reduces guesswork and builds trust immediately.&lt;/p&gt;
&lt;p&gt;Once the working example is clear, add explanation that helps the developer move forward.&lt;/p&gt;

&lt;p&gt;Focus on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what each step is doing&lt;/li&gt;
&lt;li&gt;what can be changed&lt;/li&gt;
&lt;li&gt;what to expect next&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid long sections that explain the system before the developer has seen it work.&lt;/p&gt;

&lt;p&gt;For example, instead of starting with: “Our authentication system uses token-based access with…”&lt;/p&gt;

&lt;p&gt;You can start with:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;-H "Authorization: Bearer YOUR_API_KEY"
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Then explain:&lt;/strong&gt; This header authenticates your request. Replace &lt;code&gt;YOUR_API_KEY&lt;/code&gt; with your actual key.&lt;/p&gt;

&lt;p&gt;Ideally, your explanation should support execution, not delay it.&lt;/p&gt;
&lt;p&gt;This is where most teams underestimate the problem.&lt;/p&gt;

&lt;p&gt;You need to measure how long it takes for a developer to get a working result.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many steps before the first success&lt;/li&gt;
&lt;li&gt;How long does it take to complete&lt;/li&gt;
&lt;li&gt;Where do developers get stuck&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If it takes 15–20 minutes to get a result, your tutorial is already at risk.&lt;/p&gt;

&lt;p&gt;High-converting developer tutorials aim for a working outcome within minutes, not tens of minutes&lt;/p&gt;

&lt;p&gt;You can validate this by running the tutorial from scratch, asking someone unfamiliar to try it, and observing where they hesitate or drop off&lt;/p&gt;
&lt;p&gt;Even after publishing, your tutorial is not finished.&lt;/p&gt;

&lt;p&gt;Watch for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;repeated developer questions&lt;/li&gt;
&lt;li&gt;support tickets&lt;/li&gt;
&lt;li&gt;points where users drop off&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are signals of friction. Then iterate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;simplify steps&lt;/li&gt;
&lt;li&gt;remove unnecessary complexity&lt;/li&gt;
&lt;li&gt;clarify instructions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, If multiple developers struggle with authentication, your tutorial should be updated to make that step clearer or earlier.&lt;/p&gt;

&lt;p&gt;This is the difference between tutorials that exist and tutorials that convert.&lt;/p&gt;

&lt;p&gt;Fixing developer tutorials is not about adding more content. It is about making it easier for developers to succeed.&lt;/p&gt;

&lt;p&gt;When your tutorials are built around clear outcomes, minimal setup, working examples, and fast results, they stop being just documentation. They become a reliable path to product adoption.&lt;/p&gt;

&lt;p&gt;This is what separates tutorials that get read from tutorials that convert.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer tutorials that actually convert
&lt;/h2&gt;

&lt;p&gt;Some devtools get this right. Not because they write more, but because they design tutorials around quick success.&lt;/p&gt;

&lt;p&gt;If you look closely, the pattern is consistent. The best tutorials are not trying to explain everything. They are designed to get something working as fast as possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stripe: immediate API success
&lt;/h3&gt;

&lt;p&gt;Stripe’s tutorials are built around one simple idea. Make a working API request as quickly as possible.&lt;/p&gt;

&lt;p&gt;You are not asked to understand the entire system first. You are given a clear task, a ready-to-use request, and an expected response.&lt;/p&gt;

&lt;p&gt;Within minutes, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;send a request&lt;/li&gt;
&lt;li&gt;receive a response&lt;/li&gt;
&lt;li&gt;confirm that everything works&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That first success builds confidence. From there, developers are more willing to explore deeper parts of the product.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supabase: build something real, fast
&lt;/h3&gt;

&lt;p&gt;Supabase tutorials focus on building something tangible early.&lt;/p&gt;

&lt;p&gt;Instead of abstract examples, you are guided to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a project&lt;/li&gt;
&lt;li&gt;connect to a database&lt;/li&gt;
&lt;li&gt;fetch or insert data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You are not left guessing what the end result should be. You see it happen.&lt;/p&gt;

&lt;p&gt;This makes the tutorial feel useful immediately. It is not just showing features, it is helping you achieve something that resembles a real use case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vercel: deploy and see it live
&lt;/h3&gt;

&lt;p&gt;Vercel tutorials reduce friction to the point where deployment feels instant.&lt;/p&gt;

&lt;p&gt;You go from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;connecting a repository to&lt;/li&gt;
&lt;li&gt;having a live URL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In just a few steps.&lt;/p&gt;

&lt;p&gt;There is almost no delay between action and result. That speed is what makes the experience memorable.&lt;/p&gt;

&lt;p&gt;The tutorial does not try to teach everything about deployment. It focuses on getting something live first. Everything else can come later.&lt;/p&gt;

&lt;p&gt;Across these examples, the same principles show up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you get a working result quickly&lt;/li&gt;
&lt;li&gt;the steps are clear and minimal&lt;/li&gt;
&lt;li&gt;the outcome is visible and verifiable&lt;/li&gt;
&lt;li&gt;the tutorial is tied to something real&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what high-converting developer tutorials look like.&lt;/p&gt;

&lt;p&gt;They are not longer. They are not more detailed. They are simply better designed around how developers experience progress.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Developer tutorials are not just content. They are where adoption happens. When a tutorial leads to a quick, working result, it builds confidence and keeps developers moving forward.&lt;/p&gt;

&lt;p&gt;The difference is not in how much you explain, but how quickly you help a developer succeed.&lt;/p&gt;

&lt;p&gt;At &lt;a href="https://reclear.io" rel="noopener noreferrer"&gt;Reclear&lt;/a&gt;, we help teams design and write developer tutorials and documentation that drive real product adoption. If you are looking to improve your tutorials or build them from scratch, you can &lt;a href="https://reclear.io/contact" rel="noopener noreferrer"&gt;reach out&lt;/a&gt; to see how we can help.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://reclear.io/book-a-call" rel="noopener noreferrer"&gt;Work with us&lt;/a&gt;: Book a call to discuss how we can help with your developer documentation and technical content.&lt;/p&gt;

</description>
      <category>tutorials</category>
      <category>devrel</category>
      <category>conversion</category>
    </item>
    <item>
      <title>Heroku Alternatives Decision Framework: What Actually Matters When Picking a PaaS</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Fri, 30 Jan 2026 10:43:00 +0000</pubDate>
      <link>https://dev.to/seenode/heroku-alternatives-decision-framework-what-actually-matters-when-picking-a-paas-3om3</link>
      <guid>https://dev.to/seenode/heroku-alternatives-decision-framework-what-actually-matters-when-picking-a-paas-3om3</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; After Heroku killed their free tier, everyone rushed to Railway, Render, and Fly. Three years later, here is the framework that actually matters for picking between them based on &lt;strong&gt;billing model&lt;/strong&gt;, not feature lists.&lt;/p&gt;

&lt;p&gt;When Heroku discontinued their free tier in November 2022, hundreds of thousands of projects had to migrate. Most comparison posts you will find today are just feature lists. This guide focuses on what matters &lt;strong&gt;in practice&lt;/strong&gt; after using all of these platforms in production: how they &lt;strong&gt;bill you&lt;/strong&gt; and how that interacts with your traffic pattern and your tolerance for surprise invoices.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Quick Decision Helper&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Need predictable costs?&lt;/strong&gt; → Fixed tiers (Seenode, Render)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traffic varies wildly?&lt;/strong&gt; → Usage-based (Railway, Fly.io)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Just a static site?&lt;/strong&gt; → Serverless (Vercel, Netlify)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Need enterprise features?&lt;/strong&gt; → Render&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Budget under $15/month?&lt;/strong&gt; → Seenode or self-hosted&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The One Thing Everyone Gets Wrong&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;People compare features. They should compare &lt;strong&gt;billing models&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Your choice is almost never about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Which has the best dashboard?"&lt;/li&gt;
&lt;li&gt;"Which supports my framework?"&lt;/li&gt;
&lt;li&gt;"Which has the nicest CLI?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most modern PaaS providers have reasonable dashboards, support the common languages and frameworks, and give you some batteries-included tooling. The real question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Which billing model matches your traffic pattern and your budget anxiety tolerance?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you choose the wrong model, the platform can be technically great and still feel terrible to use, because every deploy becomes a question of, &lt;em&gt;"What will the bill look like next month?"&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Migrating from Heroku?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If you're coming from Heroku's free tier, the biggest shock is usually the cost. Heroku's free tier spoiled us—most alternatives start at $4–20/month. The good news: you're getting better performance, more predictable uptime, and actual support.&lt;/p&gt;

&lt;p&gt;The closest "drop-in" replacements are &lt;strong&gt;Railway&lt;/strong&gt; (similar workflow) and &lt;strong&gt;Seenode&lt;/strong&gt; (similar economics). &lt;strong&gt;Render&lt;/strong&gt; feels more "enterprise" but costs more.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Three Billing Models That Emerged&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Over the last few years, three dominant billing models have crystallized.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Model 1: Fixed Per-Node Tiers (Seenode, Render)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You pay a flat monthly rate for provisioned capacity. Whether your app is slammed 24/7 or idle for half the month, the bill barely moves.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Predictable&lt;/strong&gt;: You know roughly what next month’s invoice will be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simple&lt;/strong&gt;: You pay for the size and count of services and databases, not for each individual CPU cycle.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wasteful at low usage&lt;/strong&gt;: You still pay even when your app is mostly idle.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Steady traffic, budget-conscious teams, and people who hate billing surprises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example costs (Jan 2026):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Seenode: &lt;strong&gt;$4/month&lt;/strong&gt; (Basic web + Tier 1 Postgres)&lt;/li&gt;
&lt;li&gt;Seenode: &lt;strong&gt;$11/month&lt;/strong&gt; (Standard web + Tier 2 Postgres)&lt;/li&gt;
&lt;li&gt;Render: &lt;strong&gt;$13/month&lt;/strong&gt; (Starter web + Basic Postgres)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your app is always on and has relatively consistent traffic, fixed tiers tend to win. You trade theoretical efficiency for billing sanity.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Model 2: Usage-Based Metering (Railway, Fly.io)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You pay for what you actually use: per-minute compute, per-second CPU, per-request, per-GB of storage and bandwidth.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Efficient at low/variable usage&lt;/strong&gt;: Quiet apps can be very cheap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scales smoothly with traffic&lt;/strong&gt;: Spikes cost more, but you do not need to resize instances manually.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unpredictable&lt;/strong&gt;: If you do not monitor usage, bills can drift or spike.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Variable traffic, developers who monitor usage, or apps that must be 24/7 online but receive low or bursty traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example costs (Jan 2026):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Railway: $20–30/month typical (Pro plan with $20 included credit), can spike to $50+ with sustained traffic.&lt;/li&gt;
&lt;li&gt;Fly.io: $0–15/month for hobby apps without managed Postgres, $43–50/month once you add managed Postgres.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usage-based systems reward teams that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instrument and monitor their apps.&lt;/li&gt;
&lt;li&gt;Understand their baseline traffic profile.&lt;/li&gt;
&lt;li&gt;Are willing to occasionally dig through billing dashboards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If that doesn't describe you, this model can feel like a tax audit every month.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Model 3: Serverless (Vercel, Netlify)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You pay per &lt;strong&gt;function invocation&lt;/strong&gt;. There is no persistent application process; instead, your code runs on demand in short-lived serverless functions.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Amazing for JAMstack&lt;/strong&gt;: Static-first sites, Next.js, Astro, Remix, etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great for spiky traffic&lt;/strong&gt;: You only pay when people actually hit your endpoints.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Awkward for stateful backends&lt;/strong&gt;: Long-lived connections, background jobs, or session-heavy apps do not fit naturally.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; JAMstack apps, modern React frameworks, marketing sites, and dashboards with lightweight APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Not suitable for:&lt;/strong&gt; Traditional backend frameworks like Django, Rails, or Express apps that rely on in-memory state, sticky sessions, or complex background processing.&lt;/p&gt;

&lt;p&gt;If your mental model of “backend” is a long-running process with queues, WebSockets, and custom workers, serverless can feel like fighting the platform instead of using it.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What It Actually Costs (Real Numbers, Jan 2026)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To make this concrete, consider a typical full-stack app:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Web service with roughly &lt;strong&gt;1 GB RAM&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Managed Postgres with &lt;strong&gt;1 GB storage&lt;/strong&gt; (plus sensible defaults)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is what that looks like across platforms today:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Billing Model&lt;/th&gt;
&lt;th&gt;What You Get&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Seenode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$11&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fixed tier&lt;/td&gt;
&lt;td&gt;Standard web + Tier 2 Postgres, always-on&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fly.io&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$12–15&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Self-managed Postgres (or $43–50/month with managed Postgres)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Railway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$20–30&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Pro plan with $20 credit, can spike with traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$57+&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Fixed tier&lt;/td&gt;
&lt;td&gt;Web service + Postgres with PITR and zero-downtime deploys&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The cliff nobody mentions:&lt;/strong&gt;  Fly.io looks cheap ($0–15) for hobby apps without managed Postgres, but once you turn on managed Postgres, the bill often jumps up rather fast ($45-50). The platform is still good—but the mental model of it being "cheap" quietly disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Decision Framework&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Stop comparing dashboards and feature checklists. Walk through these questions instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Question 1: Can you tolerate variable billing?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Yes, I monitor usage and I am okay with variance&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Choose &lt;strong&gt;Railway&lt;/strong&gt; or &lt;strong&gt;Fly.io&lt;/strong&gt;. You get flexible scaling and can squeeze out cost efficiencies if you understand your workload.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No, I need predictable monthly costs&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Choose &lt;strong&gt;Seenode&lt;/strong&gt; or &lt;strong&gt;Render&lt;/strong&gt;. Fixed tiers mean you know the number before the invoice arrives.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you feel stress every time a cloud bill arrives, treat predictability as a core feature—not a nice-to-have.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Question 2: What is your budget ceiling?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Use this as a rough mapping for a single production app with a database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$5–15/month&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Seenode&lt;/strong&gt; (Basic or Standard tiers: &lt;strong&gt;$4–11&lt;/strong&gt;/month)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosted&lt;/strong&gt; on a low-cost VPS (Hetzner, Contabo, etc.), if you are willing to manage infra.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$20–50/month&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Railway&lt;/strong&gt; (Pro plan, potentially higher with sustained traffic)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seenode&lt;/strong&gt; higher tiers if you need more resources but want fixed pricing.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$50–100/month&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render&lt;/strong&gt; (app + managed Postgres with PITR)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fly.io&lt;/strong&gt; with managed Postgres and multi-region setups.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;$100+/month&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render&lt;/strong&gt; with enterprise-style features (SSO, high availability, advanced backups).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These numbers change over time, but the &lt;strong&gt;shape&lt;/strong&gt; of the tradeoffs does not.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Question 3: Do you need enterprise features?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Yes – compliance, SOC2, SSO, PITR, zero-downtime deploys are non-negotiable&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Lean toward &lt;strong&gt;Render&lt;/strong&gt;. It is opinionated, boring in the best way, and designed for teams that want stability and support more than they want to save $20/month.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No – I mostly need HTTPS, logs, deploys, and a Postgres database&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Seenode&lt;/strong&gt; or &lt;strong&gt;Railway&lt;/strong&gt; are usually a better fit. They give you the essentials without pushing you up into enterprise pricing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If legal and compliance teams are involved, the cheapest platform is rarely the right one.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Question 4: Is global distribution critical?&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Yes – my users are spread across regions and latency matters&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Fly.io&lt;/strong&gt; shines here, with multi-region deployments as a first-class concept.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No – most users are in one region and latency is fine&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Seenode&lt;/strong&gt;, &lt;strong&gt;Railway&lt;/strong&gt;, or &lt;strong&gt;Render&lt;/strong&gt; will do the job. Focus on simplicity and billing, not on global replicas you may never need.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;What I Actually Use (and Why)&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Disclosure: I work on &lt;strong&gt;Seenode&lt;/strong&gt;, so understand the bias. That said, here is the honest breakdown of what I reach for in different scenarios.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;For hobby projects&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choice:&lt;/strong&gt; Seenode Basic (&lt;strong&gt;$4/month&lt;/strong&gt;)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; It is the &lt;strong&gt;cheapest always-on option with a database included&lt;/strong&gt; that still feels like Heroku. I can &lt;code&gt;git push&lt;/code&gt;, get HTTPS and logs, and forget about it. At $4/month, it is psychologically close to “free” but without the randomness of free-tier shutdowns.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;For client projects&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choice:&lt;/strong&gt; Render
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Clients pay for &lt;strong&gt;peace of mind&lt;/strong&gt;. Render gives you:

&lt;ul&gt;
&lt;li&gt;Managed Postgres with &lt;strong&gt;point-in-time recovery (PITR)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Zero-downtime deploys
&lt;/li&gt;
&lt;li&gt;A mature, predictable environment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The extra cost (often $57+/month for a typical setup) is easy to justify compared to the cost of a single outage for a paying client.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;For high-traffic production on a coffee-priced budget&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Choice:&lt;/strong&gt; Self-hosted on &lt;strong&gt;Hetzner&lt;/strong&gt; (or similar low-cost VPS) with &lt;strong&gt;Coolify&lt;/strong&gt; or &lt;strong&gt;Dokploy&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many services&lt;/li&gt;
&lt;li&gt;Heavy background workers&lt;/li&gt;
&lt;li&gt;Higher traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and still want to stay under &lt;strong&gt;$50/month&lt;/strong&gt;, managed PaaS platforms become harder to justify. Self-hosting:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compresses all infra cost into a single VPS bill.&lt;/li&gt;
&lt;li&gt;Gives you full control over resource allocation.&lt;/li&gt;
&lt;li&gt;Moves &lt;strong&gt;all responsibility for uptime&lt;/strong&gt; onto you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Downtime in this model is almost always your fault—bad deploys, poor monitoring, slow incident response. You save money but pay in operations time and cognitive load.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Missing Costs Nobody Mentions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Looking only at base instance prices hides a lot of real-world cost. Four common gotchas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common mistake:&lt;/strong&gt; Picking a platform based on the cheapest headline price, then getting surprised by egress fees, backup costs, or usage spikes. Always factor in the hidden costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Egress fees&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Railway: &lt;strong&gt;$0.05/GB&lt;/strong&gt; outbound&lt;/li&gt;
&lt;li&gt;Fly.io: &lt;strong&gt;$0.02/GB&lt;/strong&gt; outbound&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you run a webhook-heavy app, file-serving API, or anything data-intensive, egress can quietly add &lt;strong&gt;$50–200/month&lt;/strong&gt; on top of your compute bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Railway’s credit system&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hobby&lt;/strong&gt;: $1/month subscription with &lt;strong&gt;$5 usage credit&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro&lt;/strong&gt;: $20/month subscription with &lt;strong&gt;$20 usage credit&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once your actual usage exceeds that credit, &lt;strong&gt;metered charges&lt;/strong&gt; apply. For small apps this is fine; for growing usage it can turn into an invisible ratchet until you look closely at the billing breakdown.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Stopped machines and storage&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Fly.io continues billing &lt;strong&gt;storage&lt;/strong&gt; even when machines are stopped: around &lt;strong&gt;$0.15/GB/month&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stopping everything in a panic does not always reset the bill to zero. Persistent volumes, snapshots, and images keep ticking along until you explicitly delete them.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Database backups and safety nets&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Render&lt;/strong&gt;: Includes PITR on paid database plans. This is a genuine safety feature.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Railway / Fly.io&lt;/strong&gt;: You usually need to:

&lt;ul&gt;
&lt;li&gt;Configure backups yourself, or
&lt;/li&gt;
&lt;li&gt;Rely on third-party tools, or
&lt;/li&gt;
&lt;li&gt;Accept a more limited restore story.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is invisible until something goes wrong—and then it is the only line item that matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Closest Alternatives to OG Heroku&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;If what you really want is &lt;strong&gt;“git push and boom, we are live”&lt;/strong&gt;, here is how the modern landscape looks:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Railway&lt;/strong&gt; – Captures a lot of the Heroku magic. Simple, fast to onboard. The tradeoff is &lt;strong&gt;billing unpredictability&lt;/strong&gt; if you are not watching usage.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Seenode&lt;/strong&gt; – Leans into Heroku-style simplicity with &lt;strong&gt;Heroku-free-tier-style economics&lt;/strong&gt;. At &lt;strong&gt;$4/month&lt;/strong&gt;, it is psychologically very close to the old “free dyno” experience.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render&lt;/strong&gt; – The most &lt;strong&gt;production-ready&lt;/strong&gt; choice, especially for serious projects and client work. More expensive, but you get strong defaults and guardrails.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything else in the ecosystem is either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More serverless and front-end centric (Vercel, Netlify), or
&lt;/li&gt;
&lt;li&gt;More infra-heavy and DIY (Cloud providers, raw Kubernetes, self-hosting).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They can be great—but they are no longer "Heroku for everyone."&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Quick Comparison Summary&lt;/strong&gt;
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;th&gt;Billing Model&lt;/th&gt;
&lt;th&gt;Key Differentiator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Seenode&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hobby projects, predictable costs&lt;/td&gt;
&lt;td&gt;$4–11&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Cheapest always-on with DB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Railway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Variable traffic, Heroku-like workflow&lt;/td&gt;
&lt;td&gt;$20–30+&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Simplicity + flexibility&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Render&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client work, enterprise needs&lt;/td&gt;
&lt;td&gt;$57+&lt;/td&gt;
&lt;td&gt;Fixed&lt;/td&gt;
&lt;td&gt;Production-ready defaults&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fly.io&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Global distribution, bursty traffic&lt;/td&gt;
&lt;td&gt;$0–50+&lt;/td&gt;
&lt;td&gt;Usage-based&lt;/td&gt;
&lt;td&gt;Multi-region by default&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Key Takeaways&lt;/strong&gt;
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Billing model matters more than features&lt;/strong&gt; — Match it to your traffic pattern&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hidden costs add up&lt;/strong&gt; — Egress, storage, backups can double your bill&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Predictability vs. flexibility&lt;/strong&gt; — Choose based on your tolerance for billing surprises&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enterprise features cost money&lt;/strong&gt; — Only pay for them if you actually need them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosting saves money&lt;/strong&gt; — But you pay in operational overhead&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;So… What Should You Actually Do?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When choosing a PaaS in 2026, ask yourself one question first:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is predictable billing or pay-as-you-go flexibility more important for this project?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then layer on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How much operational burden am I willing to accept?&lt;/li&gt;
&lt;li&gt;Do I actually need global distribution, or does a single region work?&lt;/li&gt;
&lt;li&gt;Is this a hobby app, client app, or revenue-critical system?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you answer those honestly, the "Heroku alternatives" list narrows itself down very quickly.&lt;/p&gt;

&lt;p&gt;Use this checklist as you evaluate providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your stack (language, framework, database)&lt;/li&gt;
&lt;li&gt;Rough traffic pattern (requests/day or month)&lt;/li&gt;
&lt;li&gt;Maximum monthly budget&lt;/li&gt;
&lt;li&gt;Whether you need enterprise features (compliance, SSO, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With clear answers to those questions, you can quickly narrow down to one or two platforms whose billing models actually fit how your app is used.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Script automation explained – what it is, tools, benefits, and real examples</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Sun, 17 Aug 2025 16:41:00 +0000</pubDate>
      <link>https://dev.to/cloudray/script-automation-explained-what-it-is-tools-benefits-and-real-examples-1mg4</link>
      <guid>https://dev.to/cloudray/script-automation-explained-what-it-is-tools-benefits-and-real-examples-1mg4</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa28oos35arduzsl3bmo3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa28oos35arduzsl3bmo3.jpg" alt="Screenshot of adding a new setup script" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Script automation is the use of code, written in languages such as Bash, Python, or PowerShell, to automate repetitive or time‑consuming tasks in IT operations, system administration, and software development. Instead of performing tasks manually, teams can &lt;a href="https://cloudray.io/docs/scripts" rel="noopener noreferrer"&gt;run scripts&lt;/a&gt; to trigger processes such as application deployment, &lt;a href="https://cloudray.io/articles/automate-wordpress-multi-site-backups" rel="noopener noreferrer"&gt;data backups&lt;/a&gt;, file transfers, or system monitoring.&lt;/p&gt;

&lt;p&gt;Many businesses adopt script automation to reduce human error, save time, improve efficiency, and accelerate DevOps workflows. As the demand for faster software delivery and continuous integration/continuous deployment (CI/CD) grows, script automation has become an essential part of modern DevOps strategies.&lt;/p&gt;

&lt;p&gt;In this article, we explore the key benefits of script automation, popular scripting languages, top tools, and real‑world examples to help you apply it effectively in your DevOps and IT operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Best Scripting Languages for Automation&lt;/li&gt;
&lt;li&gt;Benefits of Script Automation&lt;/li&gt;
&lt;li&gt;
Top 5 Script Automation Tools

&lt;ul&gt;
&lt;li&gt;CloudRay&lt;/li&gt;
&lt;li&gt;ScriptRunner&lt;/li&gt;
&lt;li&gt;Ansible&lt;/li&gt;
&lt;li&gt;AttuneOps&lt;/li&gt;
&lt;li&gt;Jenkins&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Examples of Script Automation in Bash&lt;/li&gt;
&lt;li&gt;Wrapping up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Best Scripting Languages for Automation
&lt;/h2&gt;

&lt;p&gt;There are several programming languages for script automation with unique strengths and characteristics. However, Bash scripting and Python remain the most widely used for system and DevOps automation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Bash scripting:&lt;/strong&gt; This is a shell command language known for its integration with Unix-based systems. It’s ideal for automating administrative tasks such as package installation, server bootstrapping, or even deployments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Python:&lt;/strong&gt; This is a high-level and general purpose language widely used for infrastructure automation, API scripting, and test pipelines in modern DevOps workflows.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both Bash and Python have strengths and weaknesses depending on the use case. Below is a brief comparison:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bash&lt;/th&gt;
&lt;th&gt;Python&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Best for&lt;/td&gt;
&lt;td&gt;Shell scripting, Linux/Unix system tasks&lt;/td&gt;
&lt;td&gt;Cross-platform automation, APIs, DevOps Workflows&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ease of Use&lt;/td&gt;
&lt;td&gt;Simple for basic tasks; can get complex for logic-heavy work&lt;/td&gt;
&lt;td&gt;Readable and maintainable, especially for large scripts&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tooling &amp;amp; Ecosystem&lt;/td&gt;
&lt;td&gt;Native to Unix/Linux; tightly integrated with CLI tools&lt;/td&gt;
&lt;td&gt;Rich library ecosystem for HTTP, automation, DevOps, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Fast for command chaining and shell operations&lt;/td&gt;
&lt;td&gt;Slightly slower but better for complex logic and data parsing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Primitive error handling (exit codes)&lt;/td&gt;
&lt;td&gt;Built‑in exception handling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning Curve&lt;/td&gt;
&lt;td&gt;Easier for those familiar with Linux shell&lt;/td&gt;
&lt;td&gt;Easier for general-purpose programming and logic-heavy tasks&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Aside from Bash and Python, there are several other scripting languages for automation with each with it’s unique use cases. Here are other scripting languages widely used for IT operations and DevOps automation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Go (Golang):&lt;/strong&gt; It’s unique for task concurrent executions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;PowerShell:&lt;/strong&gt; Designed for windows automation which is great for managing system configurations and registry task&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Java:&lt;/strong&gt; Often used for DevOps pipeline automation and integrations&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ruby:&lt;/strong&gt; popular for automating configuration management&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Perl:&lt;/strong&gt; Powerful for file processing and text manipulation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JavaScript:&lt;/strong&gt; Useful for automating web APIs or build processes&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these scripting languages offers unique strengths and limitations with each one best known for specific automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Benefits of Script Automation
&lt;/h2&gt;

&lt;p&gt;The benefits of script automation are significant. As businesses scale their infrastructure and software operations, manual processes become time‑consuming, tedious, and error‑prone. Script automation boosts productivity, reduces human error, and accelerates software delivery and deployments.&lt;/p&gt;

&lt;p&gt;Here are some benefits of using script automation in DevOps workflows and IT environments:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cost Optimisation:&lt;/strong&gt; Generally, script automation reduces the need for human input which eventually cuts down human work hours and minimize costly mistake. Teams saves both time and money by automating routine tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Faster Tasks Execution:&lt;/strong&gt; Automation can execute tasks in minutes even seconds compared to manual efforts which can take hours or days to execute. Script automation leads to faster incident recovery, deployments, and even overall performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Accuracy and consistency:&lt;/strong&gt; Manual operation is error prone. However, with script automation, operations are executed with consistency across various environments.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Productivity:&lt;/strong&gt; Script automation frees up teams from repetitive tasks. This allows team to focus on higher priority work such as innovation, workflow optimisation, and security hardening.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seamless Integration with DevOps Tools&lt;/strong&gt; Scripts can be easily integrated with CI/CD and configuration management tools. They can work with this tools efficiently to trigger deployments, automate test run, and so on.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Top 5 Script Automation Tools
&lt;/h2&gt;

&lt;p&gt;Script automation tools has become important for teams that want to scale faster, increase productivity, and optimise costs. These tools empowers DevOps engineers, system admins, and cloud engineers to streamline operations.&lt;/p&gt;

&lt;p&gt;Here are top five best script automation tool used by modern engineering teams:&lt;/p&gt;

&lt;h3&gt;
  
  
  CloudRay
&lt;/h3&gt;

&lt;p&gt;CloudRay is a centralised Bash script automation platform that allows team to manage cloud and hybrid infrastructure. It allows team to run Bash scripts securely across hybrid or cloud infrastructure with the help of an &lt;a href="https://cloudray.io/docs/agent" rel="noopener noreferrer"&gt;Agent&lt;/a&gt;. This unique feature makes it suitable for automating repetitive infrastructure tasks such as Installations, deployments, server maintenance, backups and other infrastructure tasks.&lt;/p&gt;

&lt;p&gt;Additionally, &lt;a href="https://cloudray.io/docs/schedules" rel="noopener noreferrer"&gt;CloudRay’s schedules&lt;/a&gt; allow teams to schedules scripts across multiple environments. It also supports &lt;a href="https://cloudray.io/docs/incoming-webhooks" rel="noopener noreferrer"&gt;webhook triggers&lt;/a&gt;, making automation repeatable and event-driven. CloudRay stands out by combining the flexibility of scripting with the governance enterprise teams need to scale securely.&lt;/p&gt;

&lt;h3&gt;
  
  
  ScriptRunner
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.scriptrunner.com/" rel="noopener noreferrer"&gt;ScriptRunner&lt;/a&gt; is an automation platform specifically designed for PowerShell. It’s used by Windows admins to automate routine admin tasks with full auditability and governance. It provides a centralised environment for storing, managing, and executing PowerShell scripts with control and traceability. This tool also supports approvals, Active Directory integration, and delegated execution and logging.&lt;/p&gt;

&lt;h3&gt;
  
  
  Ansible
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.ansible.com/" rel="noopener noreferrer"&gt;Ansible&lt;/a&gt; is an open source configuration management tool developed by Red Hat. It uses YAML-based playbooks for infrastructure wide automation and is popular for managing complex infrastructure at scale. Ansible unique characteristics is its agentless nature in which it can operate over SSH allowing easier adoption.&lt;/p&gt;

&lt;h3&gt;
  
  
  AttuneOps
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://attuneops.io/" rel="noopener noreferrer"&gt;AttuneOps&lt;/a&gt; is a script automation tool that provides advanced orchestration, scheduling and workflow management. It supports multiple scripting languages such as PowerShell, Bash, and Python.&lt;/p&gt;

&lt;p&gt;It provides a centralised engine that allows team to automate across different OS environment consistency. It is used heavily in IT operations allowing teams to manage routine and repetitive tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Jenkins
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.jenkins.io/" rel="noopener noreferrer"&gt;Jenkins&lt;/a&gt; is the widely used automation platform for CI/CD in DevOps workflow. It excels at executing automation scripts and scheduled jobs. Jenkins supports multiple scripts such as shell and Python script. This integrates with the source control tools, and offers robust scheduling workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of Script Automation in Bash
&lt;/h2&gt;

&lt;p&gt;Bash script can be used to automate routine system administration tasks. These tasks can be installation of packages, database backups, provisioning of servers, and deployments.&lt;/p&gt;

&lt;p&gt;Let’s look at some practical examples of Bash script automation that improves IT operations and DevOps workflows:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Automating LAMP Stack Installations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bash script can be used to set up web servers quickly. You can &lt;a href="https://cloudray.io/articles/automate-installation-of-lamp-stack-on-ubuntu-using-bash-script" rel="noopener noreferrer"&gt;automate the installation of LAMP stack (Linux, Apache, MySQL, PHP)&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

set -e

# Update package list and install LAMP stack
sudo apt update
sudo apt install apache2 mysql-server php libapache2-mod-php -y

# Start services
sudo systemctl enable apache2
sudo systemctl enable mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script will install all the required components needed and ensures Apache and MySQL automatically starts on system reboot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Automating MySQL Backups to S3&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bash script can be used to automate and schedule routine database backup. For example, you can &lt;a href="https://cloudray.io/articles/automate-mysql-backup-to-amazon-s3" rel="noopener noreferrer"&gt;automate MySQL backups to Amazon S3&lt;/a&gt; to ensure your data is consistently available offsite.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

set -e

# Variables
DB_NAME="mydb"
USER="root"
PASSWORD="yourpassword"
BACKUP_PATH="/tmp/mysql-backup.sql"
DATE=$(date +%F)

mysqldump -u $USER -p$PASSWORD $DB_NAME &amp;gt; $BACKUP_PATH
aws s3 cp $BACKUP_PATH s3://your-s3-bucket/$DB_NAME-$DATE.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use it to &lt;a href="https://cloudray.io/articles/automate-postgres-backup-to-amazon-s3" rel="noopener noreferrer"&gt;automate backup of PostgreSQL to S3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Automating Installation of WordPress&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can use Bash script to streamline and automate the deployment of CMS platform like WordPress. For example, you can &lt;a href="https://cloudray.io/articles/deploy-multi-wordpress-sites-on-one-server" rel="noopener noreferrer"&gt;automate the deployment of multiple WordPress site on a single server&lt;/a&gt; with the use of Bash script.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

set -e

# Update package list and install LAMP stack
sudo apt update
sudo apt install apache2 mysql-server php php-mysql -y

# Create directories for multiple sites
sudo mkdir -p /var/www/site1.com /var/www/site2.com

# Set permissions
sudo chown -R $USER:$USER /var/www/site1.com /var/www/site2.com

# Download and extract WordPress
wget https://wordpress.org/latest.tar.gz
tar -xvzf latest.tar.gz
cp -r wordpress/* /var/www/site1.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, you can also use Bash script to &lt;a href="https://cloudray.io/articles/automate-wordpress-multi-site-backups" rel="noopener noreferrer"&gt;automate the backup process of your WordPress site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Deploy a Database Server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;infrastructure engineers use Bash scipt to save time during infrastructure setup. You can use Bash script to &lt;a href="https://cloudray.io/articles/deploy-mysql-server" rel="noopener noreferrer"&gt;automate the deployment of MySQL server&lt;/a&gt; on a Linux host.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

set -e

# Update package list and install MySQL server
sudo apt update
sudo apt install -y mysql-server
sudo systemctl enable mysql
sudo systemctl start mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Script automation is an efficient way for DevOps and IT professionals to streamline DevOps tasks, IT operations, and reduce the likelihood for human error. Whether you’re automating deployments, backups, or security checks, having a well-structured approach enhances productivity and reliability. As infrastructure grow, so does the complexity to manage these growth. Script automation becomes not just a convenience but a necessity.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://cloudray.io" rel="noopener noreferrer"&gt;CloudRay&lt;/a&gt; is a leading platform for centralised Bash script automation across your cloud and server infrastructure. With &lt;a href="https://cloudray.io/docs/agent" rel="noopener noreferrer"&gt;CloudRay Agent&lt;/a&gt;, you can securely connect your cloud instances and on-premise servers, enabling real-time execution and monitoring of scripts from a single control panel. Our powerful &lt;a href="https://cloudray.io/docs/schedules" rel="noopener noreferrer"&gt;Schedules&lt;/a&gt; feature allows you to automate scripts at custom intervals, whether hourly, daily, or triggered by specific events ensuring your DevOps workflows run reliably without manual intervention. CloudRay simplifies script management, increases operational efficiency, and gives teams full control over infrastructure automation, all from one unified interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.cloudray.io/f/auth/sign-up" rel="noopener noreferrer"&gt;Get Started with CloudRay&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Automate AWS EC2, Backups and Monitoring Using Bash Scripts</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Fri, 23 May 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cloudray/how-to-automate-aws-ec2-backups-and-monitoring-using-bash-scripts-d5j</link>
      <guid>https://dev.to/cloudray/how-to-automate-aws-ec2-backups-and-monitoring-using-bash-scripts-d5j</guid>
      <description>&lt;p&gt;Automating AWS infrastructure is a key practice for modern DevOps teams and cloud engineers. While Infrastructure as Code (IaC) tools like &lt;a href="https://developer.hashicorp.com/terraform" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; and &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html" rel="noopener noreferrer"&gt;CloudFormation&lt;/a&gt; have become the industry standard, Bash scripting remains a powerful and accessible way to automate AWS tasks. Bash scripts is especially useful for teams that wants lightweights, fast, and scriptable workflows without the overhead of learning a new Domain Specific Languages (DSL).&lt;/p&gt;

&lt;p&gt;In this article, you will learn how to automate common AWS tasks using plain Bash scripts combined with AWS CLI. Whether you’re launching EC2 instances, taking automated EBS snapshots, or setting up monitoring scripts to track CPU utilisation, Bash provides a direct and flexible approach to get things done quickly. At the end, you will learn real-world use case on how to use bash script based automation more effectively using &lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;CloudRay&lt;/a&gt; a centralised platform for managing, scheduling, executing, and organising your scripts across environments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Automation Use Cases

&lt;ul&gt;
&lt;li&gt;1. Automating EC2 Instance Launch with Bash Script&lt;/li&gt;
&lt;li&gt;2. Automating EBS Volume Backups with Bash Script&lt;/li&gt;
&lt;li&gt;3. Monitoring EC2 CPU Utilisation with Bash Script&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Real World Use Case of Automating AWS Infrastructure using CloudRay

&lt;ul&gt;
&lt;li&gt;EC2 Instance Launch with Auto-Tagging and Bootstrapping&lt;/li&gt;
&lt;li&gt;Running the Script on a Schedule with CloudRay&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Wrapping Up&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Automation Use Cases
&lt;/h2&gt;

&lt;p&gt;AWS automation is not limited to large-scale infrastructure provisioning. With just Bash and the AWS CLI, you can automate a variety of real-world tasks such as launching of instances, backing up data, and monitoring system performance. These use cases are useful when you need a quick scripts to integrate into cron jobs, CI/CD pipelines, or even internal tools.&lt;/p&gt;

&lt;p&gt;To follow along, ensure that your AWS CLI is properly installed and configured. If not, refer to the &lt;a href="https://cloudray.io/articles/aws-cli-setup-guide#installing-the-aws-cli" rel="noopener noreferrer"&gt;AWS CLI Setup Guide&lt;/a&gt; for a complete walkthrough on installing the CLI, creating key pairs, and configuring credentials.&lt;/p&gt;

&lt;p&gt;Below are some of the most practical AWS automation tasks you can implement using Bash scripts.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Automating EC2 Instance Launch with Bash Script
&lt;/h3&gt;

&lt;p&gt;Automating the creation, termination, and monitoring of EC2 instance is a common use case of AWS infrastructure management. With a simple bash script, you can reduce the manual steps and repeatability especially when managing development, staging, or even short-lived workloads for testing.&lt;/p&gt;

&lt;p&gt;To begin, create a bash script file named &lt;code&gt;launch-ec2&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano launch-ec2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following script to the file to launch EC2 instance, wait for it to become available, retrieve public IP address, and list the attached EBS volumes of the instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Launch a new EC2 instance
INSTANCE_ID=$(aws ec2 run-instances \
  --image-id ami-084568db4383264d4 \ # Replace with your preferred AMI
  --count 1 \
  --instance-type t2.micro \
  --key-name my-production-key \ # Replace with your existing key name
  --security-group-ids sg-0269249118de8b4fc \ # Replace with your Security Group ID
  --query 'Instances[0].InstanceId' \
  --output text)

echo "Launched EC2 Instance with ID: $INSTANCE_ID"

# Wait until instance is running
aws ec2 wait instance-running --instance-ids $INSTANCE_ID
echo "Instance is now running."

# Fetch public IP address
PUBLIC_IP=$(aws ec2 describe-instances \
  --instance-ids $INSTANCE_ID \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

echo "Public IP Address: $PUBLIC_IP"

# Get associated EBS Volume ID
VOLUME_ID=$(aws ec2 describe-instances \
  --instance-ids $INSTANCE_ID \
  --query 'Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId' \
  --output text)

echo "EBS Volume attached to instance: $VOLUME_ID"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what the script does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launches an EC2 instance with a specified AMI, instance type, key pair, and security group&lt;/li&gt;
&lt;li&gt;Waits for the instance to become active before proceeding&lt;/li&gt;
&lt;li&gt;Retrieves and display public IP for SSH access or web server testing&lt;/li&gt;
&lt;li&gt;Fetches the EBS Volume ID for later automation (e.g., backup snapshots or monitoring usage)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TIP&lt;/p&gt;

&lt;p&gt;Make sure you replace the AMI and security group in the script with your own AMI and security group. To get the AMI, navigate to the EC2 Console, select AMIs from the sidebar, and use filters to locate the Amazon Linux or Ubuntu image you would like to use (copy its AMI ID)&lt;/p&gt;

&lt;p&gt;Next, make your script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x launch-ec2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally you can run the scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./launch-ec2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your result would be similar to the below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4wrtlta68z5l0vwjvle.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4wrtlta68z5l0vwjvle.jpg" alt="screenshot showing output of EC2 automation on terminal" width="620" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows that the instance was created successfully and both the IP address and the EBS volume is displayed. To confirm further, you can check the AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a2ydjn6hxgby3e4np9j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0a2ydjn6hxgby3e4np9j.jpg" alt="screenshot showing output of EC2 automation on console" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see the EC2 instance running successful.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Automating EBS Volume Backups with Bash Script
&lt;/h3&gt;

&lt;p&gt;Another critical automation task is backing up your Elastic Block Store (EBS) volumes. Regular backups ensure you can recover your data in the event of accidental deletion, instance failure, or security breaches.&lt;/p&gt;

&lt;p&gt;With a Bash script, you can create snapshots of your EBS volumes on demand or integrate them into a scheduled cron job for automated backups.&lt;/p&gt;

&lt;p&gt;To get started, create a script named &lt;code&gt;backup-ebs.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano backup-ebs.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now add the following script to automate the creation of a snapshot for a given volume and tag it for easier identification:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Configuration
VOLUME_ID="vol-04fa2bf1eb229e072" # Replace with your volume ID
DESCRIPTION="Backup on $(date '+%Y-%m-%d %H:%M:%S')"
TAG_KEY="Purpose"
TAG_VALUE="AutomatedBackup"

echo "Creating snapshot of volume: $VOLUME_ID"

# Create snapshot
SNAPSHOT_ID=$(aws ec2 create-snapshot \
  --volume-id $VOLUME_ID \
  --description "$DESCRIPTION" \
  --query 'SnapshotId' \
  --output text)

echo "Snapshot created with ID: $SNAPSHOT_ID"

# Add tags to the snapshot
aws ec2 create-tags \
  --resources $SNAPSHOT_ID \
  --tags Key=$TAG_KEY,Value=$TAG_VALUE

echo "Snapshot $SNAPSHOT_ID tagged with $TAG_KEY=$TAG_VALUE"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what the script does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Takes a snapshot of a specified EBS volume using the AWS CLI&lt;/li&gt;
&lt;li&gt;Adds a human-readable description that includes the date and time of the backup&lt;/li&gt;
&lt;li&gt;Applies tags to the snapshot so you can easily search or filter for it in the AWS console&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TIP&lt;/p&gt;

&lt;p&gt;To find your EBS Volume ID, go to the EC2 Console → Volumes → and look under the “Volume ID” column. Be sure to copy the correct volume attached to your running instance.&lt;/p&gt;

&lt;p&gt;Again, make the script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x backup-ebs.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./backup-ebs.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If successful, the output should display the snapshot ID along with a confirmation that it has been tagged&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2oyklh43m91bbuoqn9f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl2oyklh43m91bbuoqn9f.jpg" alt="screenshot showing output of EBS automation on terminal" width="711" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This backup script is a great candidate for &lt;a href="https://cloudray.io/docs/schedules" rel="noopener noreferrer"&gt;CloudRay’s scheduler feature&lt;/a&gt; allowing you to run it every day, week, or hour without needing a separate server or cron job setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Monitoring EC2 CPU Utilisation with Bash Script
&lt;/h3&gt;

&lt;p&gt;System performance monitoring is essential for maintaining the health and stability of your applications. While AWS CloudWatch provides detailed metrics and dashboards, you can also automate metric checks using a simple Bash script&lt;/p&gt;

&lt;p&gt;One common metric to monitor is CPU utilisation. By querying CloudWatch, we can track when an EC2 instance’s CPU usage spikes above a defined threshold and respond accordingly.&lt;/p&gt;

&lt;p&gt;Start Start by creating a script file named &lt;code&gt;monitor-cpu.sh&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano monitor-cpu.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then paste the following code into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Configuration
INSTANCE_ID="i-044166a99d5666bfc" # Replace with your instance ID
CPU_THRESHOLD=70 # Trigger alert if CPU &amp;gt; 70%
TIME_RANGE_MINUTES=60 # How far back to check

# Fetch CPU Utilisation
CPU_UTILISATION=$(aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilisation \
  --statistics Maximum \
  --period 300 \
  --start-time $(date -u -d "$TIME_RANGE_MINUTES minutes ago" +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --dimensions Name=InstanceId,Value=$INSTANCE_ID \
  --query 'Datapoints | sort_by(@, &amp;amp;Timestamp)[-1].Maximum' \
  --output text)

# Show retrieved metric
echo "CPU Utilisation for instance $INSTANCE_ID: $CPU_UTILIZATION%"

# Check against threshold
if (( $(echo "$CPU_UTILISATION &amp;gt; $CPU_THRESHOLD" | bc -l) )); then
  echo "⚠️ High CPU alert: $INSTANCE_ID at $CPU_UTILISATION%"
else
  echo "✅ CPU usage is within safe range."
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is what the script does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Retrieves the maximum CPU utilisation from the last hour for a specific EC2 instance using CloudWatch metrics&lt;/li&gt;
&lt;li&gt;Compares it to a defined threshold (For example, 70%)&lt;/li&gt;
&lt;li&gt;Prints an alert if the usage exceeds the threshold, or a success message if within range&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make the script executable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod +x monitor-cpu.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, run the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./monitor-cpu.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your result would be similar to the below&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fte8vkaytzy84zl2vdfa3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fte8vkaytzy84zl2vdfa3.jpg" alt="screenshot showing output of EBS automation on terminal" width="728" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This lightweight monitoring script is perfect for integrating with a scheduled task on CloudRay. You can set it to run every 15 minutes and trigger custom actions like Slack alerts, emails, or remediation scripts whenever thresholds are breached.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real World Use Case of Automating AWS Infrastructure using CloudRay
&lt;/h2&gt;

&lt;p&gt;While Bash scripting gives you a powerful tool to automate AWS tasks locally, managing and reusing these scripts across environments becomes tedious without a centralised system. That is where CloudRay comes in.&lt;/p&gt;

&lt;p&gt;CloudRay provides a Scripts dashboard where you can centrally manage, execute, and reuse your infrastructure automation scripts without relying on manual CLI or scattered cron jobs. it supports scheduling, allowing you to trigger EC2 provisioning or any AWS operation at predefined times.&lt;/p&gt;

&lt;p&gt;Let’s walk through a real-world scenario where a DevOps engineer needs to launch a pre-configured EC2 instance every morning for development testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  EC2 Instance Launch with Auto-Tagging and Bootstrapping
&lt;/h3&gt;

&lt;p&gt;Before getting started, make sure your target servers are connected to CloudRay. If you haven’t done this yet, follow our &lt;a href="https://cloudray.io/docs/servers" rel="noopener noreferrer"&gt;servers docs&lt;/a&gt; to add and manage your server.&lt;/p&gt;

&lt;p&gt;You can follow the below steps to create the script in CloudRay:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffra83xgt50q2hqrct7z2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffra83xgt50q2hqrct7z2.jpg" alt="screenshot showing script creation in CloudRay" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a CloudRay account at &lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;https://app.cloudray.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Launch EC2 for Daily Dev Testing&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Optional: user data script (e.g., install NGINX on launch)
USER_DATA_SCRIPT='#!/bin/bash
sudo apt update -y
sudo apt install -y nginx
sudo systemctl enable nginx
sudo systemctl start nginx
'

echo "[$(date)] Starting EC2 launch process..." | tee -a {{log_file}}

# Launch EC2 instance
INSTANCE_ID=$(aws ec2 run-instances \
  --image-id "{{ami_id}}" \
  --count 1 \
  --instance-type "{{instance_type}}" \
  --key-name "{{key_name}}" \
  --security-group-ids "{{security_group_id}}" \
  --block-device-mappings "[{\"DeviceName\":\"/dev/xvda\",\"Ebs\":{\"VolumeSize\":{{volume_size}}}}]" \
  --tag-specifications "ResourceType=instance,Tags=[{Key=Name,Value={{tag_name}}},{Key=Environment,Value={{environment}}}]" \
  --user-data "$(echo -n "$USER_DATA_SCRIPT" | base64 -w 0)" \
  --query 'Instances[0].InstanceId' \
  --output text)

if [[-z "$INSTANCE_ID"]]; then
  echo "[$(date)] Failed to launch instance." | tee -a {{log_file}}
  exit 1
fi

echo "[$(date)] Launched instance: $INSTANCE_ID" | tee -a {{log_file}}

# Wait until running
echo "[$(date)] Waiting for instance to enter running state..." | tee -a {{log_file}}
aws ec2 wait instance-running --instance-ids "$INSTANCE_ID"
echo "[$(date)] Instance is running." | tee -a {{log_file}}

# Fetch public IP
PUBLIC_IP=$(aws ec2 describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[0].Instances[0].PublicIpAddress' \
  --output text)

LAUNCH_TIME=$(aws ec2 describe-instances \
  --instance-ids "$INSTANCE_ID" \
  --query 'Reservations[0].Instances[0].LaunchTime' \
  --output text)

echo "[$(date)] Public IP Address: $PUBLIC_IP" | tee -a {{log_file}}
echo "[$(date)] Launch Time: $LAUNCH_TIME" | tee -a {{log_file}}

# Output summary
echo ""
echo "================= EC2 Instance Launched ================="
echo "Instance ID : $INSTANCE_ID"
echo "Public IP : $PUBLIC_IP"
echo "Launch Time : $LAUNCH_TIME"
echo "Tag Name : {{tag_name}}"
echo "Environment : {{environment}}"
echo "========================================================"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script provisions a fully tagged EC2 instance, installs NGINX on launch, and logs key metadata for auditing or monitoring.&lt;/p&gt;

&lt;p&gt;Before running the scripts, you need to define values for the placeholders &lt;code&gt;{{ami_id}}&lt;/code&gt;, &lt;code&gt;{{instance_type}}&lt;/code&gt;, &lt;code&gt;{{key_name}}&lt;/code&gt; &lt;code&gt;{{security_group_id}}&lt;/code&gt;, and &lt;code&gt;{{volume_size}}&lt;/code&gt; used in the scrips. CloudRay processes all scripts as &lt;a href="https://shopify.github.io/liquid/" rel="noopener noreferrer"&gt;Liquid templates&lt;/a&gt;. This allows you to use variables dynamically across different servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplxzsawiat5ipwmvl5fh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fplxzsawiat5ipwmvl5fh.jpg" alt="Screenshot of adding a new variable group" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure that these values are automatically substituted when the script runs, follow these steps to create a variable Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Variable Groups:&lt;/strong&gt; In your CloudRay project, go to “Scripts” in the top menu and click on “Variable Groups”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a new Variable Group:&lt;/strong&gt; Click on “Variable Group”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add the following variables:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;ami_id&lt;/code&gt;:&lt;/strong&gt; This is the AMI ID of your instance type (In this case it could be Ubuntu or any other operating system)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;instance_type&lt;/code&gt;:&lt;/strong&gt; This is the type of instance you want to use&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;key_name&lt;/code&gt;:&lt;/strong&gt; The name of your private key in your AWS account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;security_group_id&lt;/code&gt;:&lt;/strong&gt; This is your security group ID&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;volume_size&lt;/code&gt;:&lt;/strong&gt; The size of your EBS volume in GB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can choose to run the script using &lt;a href="https://cloudray.io/docs/script-playlists" rel="noopener noreferrer"&gt;CloudRay’s Script Playlists&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;CloudRay uses Runlogs to execute scripts on your servers while providing real-time logs of the execution process.&lt;/p&gt;

&lt;p&gt;To run the &lt;code&gt;Launch EC2 for Daily Dev Testing&lt;/code&gt;, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Runlogs&lt;/strong&gt; : In your CloudRay project, go to the Runlogs section in the top menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a New Runlog&lt;/strong&gt; : Click on New Runlog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure the Runlog&lt;/strong&gt; : Fill in the required details:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Server: Select the server you added earlier.&lt;/li&gt;
&lt;li&gt;Script: Choose the “Launch EC2 for Daily Dev Testing”&lt;/li&gt;
&lt;li&gt;Variable Group (optional): Select the variable group you created earlier.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F36x8ajwjfp0ammtb63fo.jpg" alt="Screenshot of creating a new runlog" width="800" height="424"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Execute the Script&lt;/strong&gt; : Click on &lt;strong&gt;Run Now&lt;/strong&gt; to start the execution.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazsifk3aoww3b6cp8nw4.jpg" alt="Screenshot of the output automation script" width="800" height="417"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CloudRay will automatically connect to your server, run the &lt;code&gt;Launch EC2 for Daily Dev Testing&lt;/code&gt;, and provide live logs to track the process. If any errors occur, you can review the logs to troubleshoot the issue.&lt;/p&gt;

&lt;p&gt;You can Verify the instance also from the AWS console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0gyi3nh41gmlznp3rkx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0gyi3nh41gmlznp3rkx.jpg" alt="Screenshot of the output automation script" width="800" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the Script on a Schedule with CloudRay
&lt;/h3&gt;

&lt;p&gt;CloudRay also offers &lt;a href="https://cloudray.io/docs/schedules" rel="noopener noreferrer"&gt;Schedules&lt;/a&gt;, allowing you to execute scripts automatically at specific intervals or times.&lt;/p&gt;

&lt;p&gt;To execute this script daily at 8:00 AM without manual effort:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Schedules:&lt;/strong&gt; In your CloudRay dashboard, go to the “Schedules” tab.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftgwmt8lgq7iyvcg3wyag.jpg" alt="Screenshot of the location of Schedules in CloudRay's Interface" width="580" height="152"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click “Add Schedule”:&lt;/strong&gt; Start creating a new schedule.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi6ptkzrpyb3yhyd1hwzp.jpg" alt="Screenshot of the location of Schedules in CloudRay's Interface" width="800" height="439"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Submit Schedule:&lt;/strong&gt; Click “Submit” to activate your new schedule.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7ggn8mtpc0ybdxcgco5x.jpg" alt="Screenshot of the location of enabled schedule" width="799" height="293"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;CloudRay will automatically execute the backup script at the scheduled time, ensuring that your EC2 instance is launched regularly everyday at 8AM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Bash scripting provides a lightweight yet powerful way to automate AWS infrastructure tasks like EC2 provisioning, EBS backups, and performance monitoring. By combining these scripts with CloudRay’s scheduling and central management, you can build reliable, automated workflows without complex tooling. Start with the examples provided, customize them for your needs, and explore more automation possibilities.&lt;/p&gt;

&lt;p&gt;Start today by signing up at &lt;a href="https://app.cloudray.io" rel="noopener noreferrer"&gt;https://app.cloudray.io&lt;/a&gt; and managed your bash scripts in a centralised platform.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automating Web App Deployment with Terraform, GitHub, and CloudRay</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Thu, 10 Apr 2025 10:50:50 +0000</pubDate>
      <link>https://dev.to/cloudray/automating-web-app-deployment-with-terraform-github-and-cloudray-1noj</link>
      <guid>https://dev.to/cloudray/automating-web-app-deployment-with-terraform-github-and-cloudray-1noj</guid>
      <description>&lt;p&gt;&lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;CloudRay&lt;/a&gt; makes it easy to automate application deployment across your infrastructure. Instead of juggling manual steps or switching between tools, you can integrate CloudRay with &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; and GitHub to build a seamless deployment pipeline.&lt;/p&gt;

&lt;p&gt;In this tutorial, you will learn how to use Terraform to provision infrastructure on DigitalOcean, and then configure CloudRay to automate the deployment and management of a Node.js application. Additionally, You will also learn how to implement a simple CI/CD pipeline using GitHub Actions and &lt;a href="https://cloudray.io/docs/incoming-webhooks" rel="noopener noreferrer"&gt;CloudRay webhook&lt;/a&gt;, so every push to your repository automatically triggers a deployment.&lt;/p&gt;

&lt;p&gt;By the end, you’ll have a fully automated system that provisions a server, deploys your web app, and keeps it updated with zero manual effort.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Provisioning Infrastructure with Terraform&lt;/li&gt;
&lt;li&gt;
Configuring CloudRay for Automated Deployments

&lt;ul&gt;
&lt;li&gt;Creating Deployment Script and CloudRay Webhook&lt;/li&gt;
&lt;li&gt;Integrating CloudRay Webhook in Terraform&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Setting Up Continuous Deployment with GitHub and CloudRay&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you begin, ensure you have the following set up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Terraform installed: You can install Terraform by following the &lt;a href="https://developer.hashicorp.com/terraform/install" rel="noopener noreferrer"&gt;official instructions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;CloudRay account: Sign up at &lt;a href="https://app.cloudray.io" rel="noopener noreferrer"&gt;https://app.cloudray.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;DigitalOcean Personal Access Token: Create one via your &lt;a href="https://docs.digitalocean.com/reference/api/create-personal-access-token/" rel="noopener noreferrer"&gt;DigitalOcean control panel&lt;/a&gt;. You will need this to authenticate Terraform with DigitalOcean&lt;/li&gt;
&lt;li&gt;SSH key added to your DigitalOcean account: Create and upload a key using &lt;a href="https://cloudray.io/docs/server-keys" rel="noopener noreferrer"&gt;this guide&lt;/a&gt;. Make note of the name you assign—it will be used in your Terraform configuration&lt;/li&gt;
&lt;li&gt;GitHub repository with a sample Node.js app: For this tutorial, we’ll use a sample Node.js app stored in GitHub. You can fork and &lt;a href="https://github.com/GeoSegun/node-application-cloudray.git" rel="noopener noreferrer"&gt;clone this starter app&lt;/a&gt; or use your own&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Provisioning Infrastructure with Terraform
&lt;/h2&gt;

&lt;p&gt;Terraform lets you define infrastructure as code and supports a wide range of platforms through installable providers. Each provider acts as a bridge between Terraform and the APIs of the service you’re provisioning—like DigitalOcean in our case.&lt;/p&gt;

&lt;p&gt;We will start by using Terraform to provision a virtual machine (droplet) on DigitalOcean. This will serve as the host for our Node.js application.&lt;/p&gt;

&lt;p&gt;First, you create a project directory to house your infrastructure configuration files and navigate into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir infra-cloudray &amp;amp;&amp;amp; cd infra-cloudray
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, before running any terraform command, set the following environment variables to pass in your private SSH key and DigitalOcean API token securely. Replace the token value with your own generated token from the DigitalOcean dashboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export TF_VAR_pvt_key="~/.ssh/id_ed25519"
export TF_VAR_do_token="dop_v1_XXXXXXXXXXXXXXXXXXXXXXXXXXXX"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TIP&lt;/p&gt;

&lt;p&gt;&lt;code&gt;TF_VAR_&lt;/code&gt; prefix allows you to pass environment variables to Terraform as input variables&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;provider.tf&lt;/code&gt; which stores the configuration of the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano provider.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the following configuration into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_providers {
    digitalocean = {
      source = "digitalocean/digitalocean"
      version = "~&amp;gt; 2.0"
    }
  }
}

provider "digitalocean" {
  token = var.do_token
}

data "digitalocean_ssh_key" "my_key" {
  name = "my_key"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file sets up the Terraform provider configuration, which tells Terraform to use the DigitalOcean plugin and specifies your authentication token. Replace &lt;code&gt;my_key&lt;/code&gt; with the exact name you used when uploading your SSH key to DigitalOcean.&lt;/p&gt;

&lt;p&gt;Create the second file named &lt;code&gt;variable.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano variables.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following configurations into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "do_token" {
  description = "DigitalOcean API token"
  type = string
  sensitive = true
}

variable "pvt_key" {
  description = "Path to the private SSH key"
  type = string
  default = "~/.ssh/id_ed25519"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file declares input variables, including the DigitalOcean API token and your SSH private key path.&lt;/p&gt;

&lt;p&gt;Finally, create the main infrastructure file named &lt;code&gt;www-cloudray.tf&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano www-cloudray.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Similarly, add the following configuration inside the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "digitalocean_droplet" "www-cloudray" {
  image = "ubuntu-24-10-x64"
  name = "www-cloudray"
  region = "nyc3"
  size = "s-1vcpu-1gb"
  ssh_keys = [
    data.digitalocean_ssh_key.my_key.id
  ]

  connection {
    host = self.ipv4_address
    user = "root"
    type = "ssh"
    private_key = file(var.pvt_key)
    timeout = "2m"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the main infrastructure file where we define our server. We use Ubuntu 24.10 and connect via SSH using your uploaded key. Furthermore, the configuration tells terraform to create a droplet named “www-cloudray”, use the SSH key you added to DigitalOcean and automatically connect connect using SSH for further provisioning.&lt;/p&gt;

&lt;p&gt;Now, you initialize the terraform file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75t2m0brzfwjhohogrve.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75t2m0brzfwjhohogrve.jpg" alt="Screenshot of successful initiallisation" width="800" height="274"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, you run the &lt;code&gt;terraform plan&lt;/code&gt; to see your execution plan:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform plan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqgidz5u2ioocgus817m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnqgidz5u2ioocgus817m.jpg" alt="Screenshot of terraform plan output" width="800" height="475"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;+ resource "digitalocean_droplet" "www-cloudray"&lt;/code&gt; shows that terraform will create a droplet resources named &lt;code&gt;www-cloudray&lt;/code&gt;. Then, apply the configuration by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When prompted, type &lt;code&gt;yes&lt;/code&gt; to confirm.&lt;/p&gt;

&lt;p&gt;After deployment, you can inspect the created infrastructure and get the server’s IP address using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform show terraform.tfstate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdqip6g69rcpip3ugkwc.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsdqip6g69rcpip3ugkwc.jpg" alt="Screenshot of showing server details" width="544" height="534"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, you can &lt;a href="https://cloudray.io/docs/servers" rel="noopener noreferrer"&gt;add the server to CloudRay&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring CloudRay for Automated Deployments
&lt;/h2&gt;

&lt;p&gt;Now that your DigitalOcean droplet is provisioned and added to CloudRay, let’s automate deployments using CloudRay’s script orchestration. This section covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creating a deployment script and webhook&lt;/li&gt;
&lt;li&gt;Modifying Terraform to trigger deployment of the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s get started.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Deployment Script and CloudRay Webhook
&lt;/h3&gt;

&lt;p&gt;First you create the deployment script by following these steps:&lt;/p&gt;

&lt;p&gt;To create the setup script, you need to follow this steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnm6xmqucb4cl0kuyrek.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnm6xmqucb4cl0kuyrek.jpg" alt="Screenshot of adding a new deployment script" width="754" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; in your CloudRay project&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Deploy App Script&lt;/code&gt;. You can give it any name of your choice&lt;/li&gt;
&lt;li&gt;Copy this code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Update package lists
sudo apt update -y

# Install Nginx
sudo apt update 
sudo apt install -y nginx 

# Exit on error
set -e

# Install Node.js and npm
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install -y nodejs

# Install PM2
sudo npm install -g pm2

# Clean and clone repo
sudo rm -rf "{{app_dir}}"
sudo mkdir -p "{{app_dir}}"
sudo chown -R $USER:$USER "{{app_dir}}"
git clone "{{repo_url}}" "{{app_dir}}"

# Install dependencies
cd "{{app_dir}}/app"
npm install

# Start application
pm2 start server.js --name nodeapp
pm2 save
pm2 startup

sudo bash -c "cat &amp;gt; /etc/nginx/sites-available/nodeapp" &amp;lt;&amp;lt;EOF
server {
    listen 80;
    server_name {{domain}} www.{{domain}};
    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade \$http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host \$host;
        proxy_cache_bypass \$http_upgrade;
    }
}
EOF

# Enable config
sudo ln -sf /etc/nginx/sites-available/nodeapp /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

# SSL with Certbot
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d {{domain}} -d www.{{domain}} --email {{email}} --agree-tos --non-interactive
sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a breakdown of what each command in the &lt;code&gt;Deploy App Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets up the web server and runtime environment&lt;/li&gt;
&lt;li&gt;Clones your Node.js repository and installs dependencies&lt;/li&gt;
&lt;li&gt;Runs app as a managed background service&lt;/li&gt;
&lt;li&gt;Routes web traffic to your Node.js app&lt;/li&gt;
&lt;li&gt;Automatically provisions Let’s Encrypt SSL certificates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;before using the scripts, you need to define values for the placeholders &lt;code&gt;{{app_dir}}&lt;/code&gt;, &lt;code&gt;{{repo_url}}&lt;/code&gt;, &lt;code&gt;{{domain}}&lt;/code&gt;, and &lt;code&gt;{{email}}&lt;/code&gt;, used in the scrips. CloudRay processes all scripts as &lt;a href="https://shopify.github.io/liquid/" rel="noopener noreferrer"&gt;Liquid templates&lt;/a&gt;. This allows you to use variables dynamically across different servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sg1z23c3g0l7wndlgd3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sg1z23c3g0l7wndlgd3.jpg" alt="Screenshot of adding a new variable group" width="780" height="524"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure that these values are automatically substituted when the script runs, follow these steps to create a variable Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Variable Groups:&lt;/strong&gt; In your CloudRay project, go to “Scripts” in the top menu and click on “Variable Groups”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a new Variable Group:&lt;/strong&gt; Click on “Variable Group”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add the following variables:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;{{app_dir}}&lt;/code&gt;:&lt;/strong&gt; This is the application install path&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;{{repo_url}}&lt;/code&gt;:&lt;/strong&gt; This is the GitHub repository URL&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;domain&lt;/code&gt;:&lt;/strong&gt; The registered domain name for SSL certificate configuration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;email&lt;/code&gt;:&lt;/strong&gt; The email address associated with the SSL certificate (used for renewal alerts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the script and variables are setup, proceed to creating a Webhook for the deployment script.&lt;/p&gt;

&lt;p&gt;To create an &lt;a href="https://cloudray.io/docs/incoming-webhooks" rel="noopener noreferrer"&gt;Incoming Webhook&lt;/a&gt; in CloudRay follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In CloudRay navigate and click on “Incoming Webhooks”&lt;/li&gt;
&lt;li&gt;Click on “New Incoming Webhook” and fill in the detials to create the Webhook
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot0v5v922f3cjpdwqktg.jpg" alt="Screenshot of creating a webhook" width="762" height="612"&gt;
&lt;/li&gt;
&lt;li&gt;Click “Create New Webhook”. This will generate a unique URL for your webhook
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fot0v5v922f3cjpdwqktg.jpg" alt="Screenshot of created webhook" width="762" height="612"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that your deployment script and CloudRay webhook are ready, the final step is to make sure Terraform can trigger that webhook&lt;/p&gt;

&lt;h3&gt;
  
  
  Integrating CloudRay Webhook in Terraform
&lt;/h3&gt;

&lt;p&gt;We can update our Terraform configuration to trigger the CloudRay webhook after the droplet is successfully provisioned. Instead of using the &lt;code&gt;remote-exec&lt;/code&gt; provisioner, we use a &lt;code&gt;null_resource&lt;/code&gt; block with a &lt;code&gt;local-exec&lt;/code&gt; provisioner, which runs the webhook call locally from the machine running Terraform.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;www-cloudray.tf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nano www-cloudray.tf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add the following &lt;code&gt;null_resource&lt;/code&gt; configuration outside the droplet block:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
resource "null_resource" "trigger_cloudray_webhook" {
  provisioner "local-exec" {
    command = &amp;lt;&amp;lt;EOT
      curl -X POST \
        https://api.cloudray.io/w/58b3b37d-a77c-4b22-a6bc-ef3e2af8af34 \
        -H "Content-Type: application/json" \
        -d '{"test": false}'
    EOT
  }

  depends_on = [digitalocean_droplet.www-cloudray]
}
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This tells Terraform to trigger the CloudRay webhook only after the &lt;code&gt;www-cloudray&lt;/code&gt; droplet has been successfully created.&lt;/p&gt;

&lt;p&gt;Your updated &lt;code&gt;www-cloudray.tf&lt;/code&gt; file should now look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2a0o4yi41jw5483om57.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr2a0o4yi41jw5483om57.jpg" alt="Screenshot of new wwww-cloudray.tf file" width="630" height="346"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This approach ensures that the webhook is triggered reliably during the provisioning process without the need for SSH access into the droplet.&lt;/p&gt;

&lt;p&gt;Before applying your changes, reinitialize your Terraform project and upgrade any modules or providers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform init -upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then apply the configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once terraform apply completes successfully, head over to your &lt;a href="https://cloudray.io/docs/runlogs" rel="noopener noreferrer"&gt;CloudRay Runlog&lt;/a&gt; to confirm that the webhook was received and the deployment job ran successfully.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ly0lgyi597lmj9v67gd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9ly0lgyi597lmj9v67gd.jpg" alt="Screenshot of successful Runlog" width="799" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Open your browser and navigate to your configured domain (e.g., &lt;a href="https://www.mydomain.com" rel="noopener noreferrer"&gt;https://www.mydomain.com&lt;/a&gt;). You should now see your application live and running on the newly provisioned droplet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6pjohlydgoxdg6jqwr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyy6pjohlydgoxdg6jqwr.jpg" alt="Screenshot of successful Runlog" width="800" height="466"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Continuous Deployment with GitHub and CloudRay
&lt;/h2&gt;

&lt;p&gt;To automate your deployment pipeline, we’ll integrate GitHub Actions with CloudRay so that any push to the &lt;code&gt;main&lt;/code&gt; branch triggers a webhook, which then updates your server with the latest code.&lt;/p&gt;

&lt;p&gt;First, let’s create the script on CloudRay to update always update the application. You can follow similar process as the above and use this code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftsyt0u7kdlcdyuo2tu3m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftsyt0u7kdlcdyuo2tu3m.jpg" alt="Screenshot of setup CI" width="706" height="826"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash
set -e # Exit immediately if any command fails

# Navigate to project root
cd /var/www/nodeapp

echo "➡️ Pulling latest changes..."
git pull origin main

# Move to app directory
cd app

echo "📦 Installing dependencies..."
npm install

echo "🔄 Restarting application..."
pm2 restart nodeapp || (pm2 delete nodeapp &amp;amp;&amp;amp; pm2 start server.js --name nodeapp)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we also create a Webhook following similar steps as discussed earlier&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft977lpxlv4fdm7iqgf6m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft977lpxlv4fdm7iqgf6m.jpg" alt="Screenshot of setup CI" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then go to the project repository (the node.js application), create a directory and file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir -p .github/workflows
touch .github/workflows/deploy.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then add the following content to &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: Deploy to CloudRay

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Trigger CloudRay Webhook
        env:
          WEBHOOK_URL: ${{ secrets.CLOUDRAY_WEBHOOK }}
        run: |
          curl -X POST "$WEBHOOK_URL" \
            -H "Content-Type: application/json" \
            -d '{"test": false}'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To add your CloudRay webhook to GitHub secrets, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlv7zpyugpwlcje37q7v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftlv7zpyugpwlcje37q7v.jpg" alt="Screenshot of first addition of GitHub secret step" width="800" height="665"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to your GitHub repo Settings → Secrets → Actions&lt;/li&gt;
&lt;li&gt;Click “New repository secret”
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpkfph5zpm0ycg0vmvpi2.jpg" alt="Screenshot of first addition of GitHub secret step" width="800" height="360"&gt;
&lt;/li&gt;
&lt;li&gt;Name: CLOUDRAY_WEBHOOK&lt;/li&gt;
&lt;li&gt;Value: Paste your CloudRay webhook URL&lt;/li&gt;
&lt;li&gt;Click “Add secret”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, let’s test the pipeline, make a changes on the application (modify the &lt;code&gt;index.html&lt;/code&gt; file):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html lang="en"&amp;gt;
&amp;lt;head&amp;gt;
    &amp;lt;meta charset="UTF-8"&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;
    &amp;lt;title&amp;gt;Welcome&amp;lt;/title&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Greetings from CloudRay&amp;lt;/h1&amp;gt;
    &amp;lt;p&amp;gt;This update was deployed automatically via GitHub → CloudRay 🎉&amp;lt;/p&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit and push to main:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git add .
git commit -m "Test CI/CD pipeline"
git push origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Watch the process, GitHub Actions will show the workflow running.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8pivhtf6kqktvp1vuj6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg8pivhtf6kqktvp1vuj6.jpg" alt="Screenshot of first addition of GitHub secret step" width="799" height="148"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additionally, CloudRay will display the script execution in Run Logs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lu4v12kqje9c5f0hd2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0lu4v12kqje9c5f0hd2.jpg" alt="Screenshot of first addition of GitHub secret step" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, visit your domain to see changes live within seconds.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmin8dgpbyp26sor4xpi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnmin8dgpbyp26sor4xpi.jpg" alt="Screenshot of first addition of GitHub secret step" width="694" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By following this guide, you’ve successfully built a complete infrastructure automation and CI/CD pipeline that combines Terraform, DigitalOcean, CloudRay, and GitHub Actions.&lt;/p&gt;

&lt;p&gt;The entire process from server creation to application updates now happens automatically whenever you push code changes, giving you more time to focus on development rather than deployment tasks.&lt;/p&gt;

&lt;p&gt;Ready to streamline your own deployment workflow? &lt;a href="https://app.cloudray.io" rel="noopener noreferrer"&gt;Sign up for CloudRay today&lt;/a&gt; and experience the power of infrastructure automation firsthand.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.cloudray.io/f/auth/sign-up" rel="noopener noreferrer"&gt;Get Started with CloudRay&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deploy a Laravel Application using CloudRay</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Thu, 03 Apr 2025 12:34:35 +0000</pubDate>
      <link>https://dev.to/cloudray/deploy-a-laravel-application-using-cloudray-2f85</link>
      <guid>https://dev.to/cloudray/deploy-a-laravel-application-using-cloudray-2f85</guid>
      <description>&lt;p&gt;&lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;CloudRay&lt;/a&gt; simplifies infrastructure deployment through automation, making it an ideal choice for managing Laravel applications with Caddy. It automates the entire deployment process, reducing manual effort and ensuring a seamless, repeatable setup.&lt;/p&gt;

&lt;p&gt;In this guide, you will learn the process of deploying a Laravel application with Caddy using CloudRay. You will learn how to create a detailed automation script for setting up the system, installing dependencies, deploying Laravel, and configuring Caddy as the web server. Caddy simplifies the process by automatically handling HTTPS (SSL/TLS) with Let’s Encrypt, ensuring your application is secure by default.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you will have a fully functional Laravel application hosted on an optimised server environment with automatic SSL support provided by Caddy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Assumptions&lt;/li&gt;
&lt;li&gt;
Create the Automation Script

&lt;ul&gt;
&lt;li&gt;System Setup Script&lt;/li&gt;
&lt;li&gt;Install Composer and Database Setup Script&lt;/li&gt;
&lt;li&gt;Laravel Deployment Script&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create a Variable Group&lt;/li&gt;
&lt;li&gt;Running the Script with CloudRay&lt;/li&gt;
&lt;li&gt;Troubleshooting&lt;/li&gt;
&lt;li&gt;Related Guides&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before getting started, make sure you have the following prerequisites in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A CloudRay account&lt;/strong&gt; at &lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;https://app.cloudray.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A cloud server accessible via SSH:&lt;/strong&gt; If you don’t already have a cloud server, you can get one from popular providers like &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;, &lt;a href="https://www.digitalocean.com/" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt;, and &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud&lt;/a&gt;. Ensure the server has at least 4GB of RAM, and a minimum of 20GB SSD&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH credentials:&lt;/strong&gt; Ensure you have access to the necessary SSH keys or login credentials to access your server. If you don’t have an SSH key set up, follow &lt;a href="https://dev.to/docs/server-keys"&gt;this guide&lt;/a&gt; to create one and add it to CloudRay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The servers are added to CloudRay:&lt;/strong&gt; Before proceeding, make sure your server is connected to CloudRay. If you haven’t done this yet, follow &lt;a href="https://cloudray.io/docs/servers" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to add and manage your server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;This guide uses Bash scripts, providing a high degree of customisation. You can adapt the scripts to fit your specific deployments needs and environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This guide assumes you’re using &lt;strong&gt;Rocky Linux 9&lt;/strong&gt; as your server’s operating system. If you’re using a different version or a different distribution, adjust the commands accordingly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the Automation Script
&lt;/h2&gt;

&lt;p&gt;To streamline the deployment process, you can use three automation scripts&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;System Setup Script:&lt;/strong&gt; Installs all the Lavarel application and systems dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Install Composer and Database Setup Script:&lt;/strong&gt; Installs composer and setup the Laravel database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laravel Deployment Script:&lt;/strong&gt; automates cloning, configuring, and deploying a Laravel app with Caddy&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s begin with the System Setup Script&lt;/p&gt;

&lt;h3&gt;
  
  
  System Setup Script
&lt;/h3&gt;

&lt;p&gt;To create the System Setup Script, you need to follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2k52spzdltm1hs8h9nia.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2k52spzdltm1hs8h9nia.jpg" alt="Screenshot of adding a new system setup script" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; in your CloudRay project&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;System Setup Script&lt;/code&gt;. You can give it any name of your choice&lt;/li&gt;
&lt;li&gt;Copy this code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# exit on error
set -e

# Update system
sudo dnf update -y

# Install required software
sudo dnf install -y mariadb-server php php-fpm php-common php-xml php-mbstring php-json php-zip php-mysqlnd curl unzip nano

# Start and enable services
sudo systemctl start mariadb php-fpm
sudo systemctl enable mariadb php-fpm

# Configure PHP-FPM
sudo sed -i 's/^;listen.owner =.*/listen.owner = www-data/' /etc/php-fpm.d/www.conf
sudo sed -i 's/^;listen.group =.*/listen.group = www-data/' /etc/php-fpm.d/www.conf

sudo systemctl restart php-fpm

# Set SELinux to permissive mode
sudo setenforce 0

# Add /usr/local/bin to secure path in sudoers
sudo sed -i '/Defaults\s\+secure_path = /s|\(.*\)|\1:/usr/local/bin|' /etc/sudoers

echo "System setup complete!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a breakdown of what each command in the &lt;code&gt;System Setup Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates the system to the latest packages&lt;/li&gt;
&lt;li&gt;Installs MariaDB, PHP, and dependencies required for Laravel&lt;/li&gt;
&lt;li&gt;Starts and enables services to launch on boot&lt;/li&gt;
&lt;li&gt;Configures PHP-FPM to use www-data as the owner&lt;/li&gt;
&lt;li&gt;Configures SELinux to be permissive (optional, for easier troubleshooting)&lt;/li&gt;
&lt;li&gt;Adds &lt;code&gt;/usr/local/bin&lt;/code&gt; to the secure path for sudo commands&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Install Composer and Database Setup Script
&lt;/h3&gt;

&lt;p&gt;Next, you need to install and setup the database for the Laravel application. To do so, follow similar steps as the above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop7s9dc27x1q4xw3iixd.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fop7s9dc27x1q4xw3iixd.jpg" alt="Screenshot of installing composer and database setup" width="708" height="822"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Install Composer and Database Setup Script&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Exit on error
set -e

# Install Composer
curl -sS https://getcomposer.org/installer | php
sudo mv composer.phar /usr/local/bin/composer
sudo chmod +x /usr/local/bin/composer

# Verify Composer installation
composer --version

# Configure MySQL database
sudo mysql &amp;lt;&amp;lt;EOF
CREATE DATABASE {{db_name}};
CREATE USER '{{db_user}}'@'localhost' IDENTIFIED BY '{{db_pass}}';
GRANT ALL PRIVILEGES ON {{db_name}}.* TO '{{db_user}}'@'localhost';
FLUSH PRIVILEGES;
EOF

echo "Composer and MySQL setup complete!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what the &lt;code&gt;Install Composer and Database Setup Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installs Composer, a dependency manager for PHP&lt;/li&gt;
&lt;li&gt;Verifies Composer installation to ensure it’s available system-wide&lt;/li&gt;
&lt;li&gt;Configures MariaDB database by creating a database, user, and granting permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Laravel Deployment Script
&lt;/h3&gt;

&lt;p&gt;The final script automates the cloning, configuration, and deployment of your Laravel application with Caddy. This script will handle the deployment process, ensuring your application is ready to serve traffic.&lt;/p&gt;

&lt;p&gt;To create the Laravel Deployment Script, follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1mczz3jv4t5sb2garhf.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk1mczz3jv4t5sb2garhf.jpg" alt="Screenshot of deploying Laravel application" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Laravel Deployment Script&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/bin/bash

# Exit on error
set -e

# install git
sudo dnf install git -y

# Install Caddy
sudo dnf install 'dnf-command(copr)' -y
sudo dnf copr enable @caddy/caddy -y
sudo dnf install caddy -y

# Start and enable Caddy
sudo systemctl start caddy
sudo systemctl enable caddy

# Clone Laravel project from GitHub
if [! -d "/var/www/html/{{repo_name}}"]; then
    echo "Cloning Laravel repository from GitHub..."
    sudo git clone https://{{github_access_token}}@github.com/{{github_user}}/{{repo_name}}.git /var/www/html/{{repo_name}}
else
    echo "Repository already exists. Fetching latest changes..."
    cd /var/www/html/{{repo_name}}
    sudo git fetch --all
    echo "Resetting to the latest version of the main branch..."
    sudo git reset --hard origin/main
fi

# Set correct permissions
sudo chown -R www-data:www-data /var/www/html/{{repo_name}}/storage
sudo chown -R www-data:www-data /var/www/html/{{repo_name}}/bootstrap/cache
sudo chmod -R 775 /var/www/html/{{repo_name}}/storage
sudo chmod -R 775 /var/www/html/{{repo_name}}/bootstrap/cache

# Update Laravel environment file
if [-f "/var/www/html/{{repo_name}}/.env"]; then
    echo "Updating existing .env file..."
    # Update existing variables
    sudo sed -i "s|^APP_URL=.*|APP_URL={{domain}}|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_CONNECTION=.*|DB_CONNECTION=mysql|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_HOST=.*|DB_HOST=127.0.0.1|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_PORT=.*|DB_PORT=3306|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_DATABASE=.*|DB_DATABASE={{db_name}}|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_USERNAME=.*|DB_USERNAME={{db_user}}|" /var/www/html/{{repo_name}}/.env
    sudo sed -i "s|^DB_PASSWORD=.*|DB_PASSWORD={{db_pass}}|" /var/www/html/{{repo_name}}/.env
else
    echo "Creating new .env file..."
    cat &amp;lt;&amp;lt;EOL | sudo tee /var/www/html/{{repo_name}}/.env
APP_URL={{domain}}

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE={{db_name}}
DB_USERNAME={{db_user}}
DB_PASSWORD={{db_pass}}
EOL
fi

# Run Laravel setup commands
cd /var/www/html/{{repo_name}}
sudo php artisan key:generate
sudo php artisan migrate

# Configure Caddy
cat &amp;lt;&amp;lt;EOL | sudo tee /etc/caddy/Caddyfile
{{domain}} {
    root * /var/www/html/{{repo_name}}/public # Serve files from the Laravel public directory
    php_fastcgi unix//run/php-fpm/www.sock # Pass PHP requests to PHP-FPM
    file_server # Serve static files
}
EOL

# Start and enable Caddy
sudo systemctl start caddy
sudo systemctl enable caddy

# Install Firewall &amp;amp; Configure Rules
sudo dnf install -y firewalld
sudo systemctl start firewalld
sudo systemctl enable firewalld
sudo firewall-cmd --zone=public --permanent --add-service=http
sudo firewall-cmd --zone=public --permanent --add-service=https
sudo firewall-cmd --reload

echo "Laravel deployment and SSL setup complete!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what the &lt;code&gt;Laravel Deployment Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installs Git for repository cloning&lt;/li&gt;
&lt;li&gt;Defines the GitHub repository and target directory&lt;/li&gt;
&lt;li&gt;Clones the Laravel project or updates it if it already exists&lt;/li&gt;
&lt;li&gt;Sets proper permissions for storage and cache directories&lt;/li&gt;
&lt;li&gt;Runs Laravel migration and key generation to prepare the application&lt;/li&gt;
&lt;li&gt;Deploy the application with Caddy&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a Variable Group
&lt;/h2&gt;

&lt;p&gt;Now, before running the scripts, you need to define values for the placeholders &lt;code&gt;{{db_name}}&lt;/code&gt;, &lt;code&gt;{{db_user}}&lt;/code&gt;, &lt;code&gt;{{db_pass}}&lt;/code&gt;, &lt;code&gt;{{github_access_token}}&lt;/code&gt;, &lt;code&gt;{{github_user}}&lt;/code&gt;, &lt;code&gt;{{repo_name}}&lt;/code&gt;, and &lt;code&gt;{{domain}}&lt;/code&gt; used in the scrips. CloudRay processes all scripts as &lt;a href="https://shopify.github.io/liquid/" rel="noopener noreferrer"&gt;Liquid templates&lt;/a&gt;. This allows you to use variables dynamically across different servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Froyvhxwpkyf8m7kvzxtv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Froyvhxwpkyf8m7kvzxtv.jpg" alt="Screenshot of adding a new variable group" width="746" height="696"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure that these values are automatically substituted when the script runs, follow these steps to create a variable Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Variable Groups:&lt;/strong&gt; In your CloudRay project, go to “Scripts” in the top menu and click on “Variable Groups”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a new Variable Group:&lt;/strong&gt; Click on “Variable Group”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add the following variables:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;db_name&lt;/code&gt;:&lt;/strong&gt; This is the name database for the Laravel application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;db_user&lt;/code&gt;:&lt;/strong&gt; Database user for the Laravel application&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;db_pass&lt;/code&gt;:&lt;/strong&gt; Password for the database user&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;github_access_token&lt;/code&gt;:&lt;/strong&gt; This is your GitHub personal access token for cloning the repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;github_user&lt;/code&gt;:&lt;/strong&gt; This is your GitHub Username&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;repo_name&lt;/code&gt;:&lt;/strong&gt; This is the name of the GitHub repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;domain&lt;/code&gt;:&lt;/strong&gt; Domain name for the Laravel application e.g., &lt;code&gt;myapp.com&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the variables are setup, proceed to run the scripts with CloudRay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Script with CloudRay
&lt;/h2&gt;

&lt;p&gt;Now that everything is setup, you can use CloudRay to automate the deployment of your Laravel Application&lt;/p&gt;

&lt;p&gt;You can choose to run the scripts individually or execute them all at once using &lt;a href="https://cloudray.io/docs/script-playlists" rel="noopener noreferrer"&gt;CloudRay’s Script Playlists&lt;/a&gt;. Since there are multiple scripts, using CloudRay playlists will help automate the execution sequence and save time.&lt;/p&gt;

&lt;p&gt;Here are the steps to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to “Script Playlists”:&lt;/strong&gt; Click on the Scripts tab in the CloudRay interface
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrlryxkjcc4ct3xpud39.jpg" alt="Locate the script playlist in CloudRay interface" width="512" height="186"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click “Add Script Playlist”:&lt;/strong&gt; This initiates the creation of a new playlist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide a Name:&lt;/strong&gt; Give your playlist a unique name (For example “Automate Deployment and Management of Laravel Application”)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add Scripts in Order:&lt;/strong&gt; Select and add the scripts sequentially
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7lflj9s5wt2i7vedav32.jpg" alt="Locate the script playlist in CloudRay interface" width="600" height="498"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save the Playlist:&lt;/strong&gt; Click “create playlist” to store your new playlist.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once your script playlist is created, proceed with execution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Runlogs&lt;/strong&gt; : In your CloudRay project, go to the Runlogs section in the top menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a New Runlog&lt;/strong&gt; : Click on New Runlog&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure the Runlog&lt;/strong&gt; : Provide the necessary details:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgb04qdcyzpgtecsakvwz.jpg" alt="Screenshot of creating a new runlog" width="638" height="432"&gt;
&lt;/li&gt;
&lt;li&gt;Server: Select the server where your Laravel application will be installed&lt;/li&gt;
&lt;li&gt;Script Playlist: Choose the playlist you created (For example “Automate Deployment and Management of Laravel Application”)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Variable Group: Select the variable group you set up earlier&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execute the Script&lt;/strong&gt; : Click on &lt;strong&gt;Run Now&lt;/strong&gt; to start the execution&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsvm54mgxijxct0xqrh8.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnsvm54mgxijxct0xqrh8.jpg" alt="Screenshot of the result of all the script from the script playlist" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your Laravel Application is now seamlessly deployed and managed with CloudRay. That’s it! Happy deploying!. You can access it by visiting &lt;code&gt;http://myapp.com&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;If you encounter issues during deployment, consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caddy Fails to Start:&lt;/strong&gt; Check the Caddy service status with &lt;code&gt;sudo systemctl status caddy&lt;/code&gt; and restart it using &lt;code&gt;sudo systemctl restart caddy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PHP-FPM Not Working:&lt;/strong&gt; Ensure PHP-FPM is running with &lt;code&gt;sudo systemctl status php-fpm&lt;/code&gt; and restart it using &lt;code&gt;sudo systemctl restart php-fpm&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Certificate Not Issued:&lt;/strong&gt; Verify your domain’s DNS records and ensure ports 80 and 443 are open in the firewall.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Laravel Application Not Loading:&lt;/strong&gt; Check the &lt;code&gt;.env&lt;/code&gt; file for correct database credentials and ensure the storage and &lt;code&gt;bootstrap/cache&lt;/code&gt; directories have the correct permissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Connection Issues:&lt;/strong&gt; Verify the database credentials in the &lt;code&gt;.env&lt;/code&gt; file and ensure MariaDB is running with &lt;code&gt;sudo systemctl status mariadb&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the issue persists, consult the &lt;a href="https://caddyserver.com/docs/" rel="noopener noreferrer"&gt;Caddy Documentation&lt;/a&gt; or the &lt;a href="https://laravel.com/docs/12.x/readme" rel="noopener noreferrer"&gt;Laravel Documentation&lt;/a&gt; for further assistance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/articles/deploy-express"&gt;Deploy Node &amp;amp; Express&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/articles/deploy-ruby-on-rails"&gt;Deploy Ruby on rails app&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/articles/deploy-phpmyadmin"&gt;How to Deploy phpMyAdmin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/articles/deploy-jenkins-with-docker-compose"&gt;Deploy Jenkins with Docker Compose&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://app.cloudray.io/f/auth/sign-up" rel="noopener noreferrer"&gt;Get Started with CloudRay&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Automate the Installation of Nagios Using CloudRay</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Thu, 06 Mar 2025 00:00:00 +0000</pubDate>
      <link>https://dev.to/cloudray/automate-the-installation-of-nagios-using-cloudray-3dgo</link>
      <guid>https://dev.to/cloudray/automate-the-installation-of-nagios-using-cloudray-3dgo</guid>
      <description>&lt;p&gt;Automating the installation of Nagios on Rocky Linux 9 ensures consistency, reduces errors, and saves time when setting up monitoring for your environment. &lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;CloudRay&lt;/a&gt; a powerful automation tool, enables seamless setup, deployment, and management of Nagios. By leveraging CloudRay, you can automate the setting up, configurations, and deployment of Nagios.&lt;/p&gt;

&lt;p&gt;In this guide, you will learn how to automate the installation of Nagios Core on Rocky Linux 9 using CloudRay.&lt;/p&gt;

&lt;p&gt;IMPORTANT&lt;/p&gt;

&lt;p&gt;This article focuses on installing Nagios Core on Rocky Linux 9 using CloudRay. If you’re looking to monitor remote hosts using NRPE, check out our companion guide: &lt;a href="https://dev.to/articles/monitor-remote-hosts-with-nagios"&gt;How to Monitor Remote Hosts with Nagios Using CloudRay&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Assumptions&lt;/li&gt;
&lt;li&gt;
Create the Automation Script

&lt;ul&gt;
&lt;li&gt;Setup Nagios Script&lt;/li&gt;
&lt;li&gt;Deploy Nagios Script&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Create a Variable Group&lt;/li&gt;
&lt;li&gt;Running the Scripts to Install Nagios with CloudRay&lt;/li&gt;
&lt;li&gt;Troubleshooting&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before getting started, make sure you have the following prerequisites in place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A CloudRay account&lt;/strong&gt; at &lt;a href="https://app.cloudray.io/" rel="noopener noreferrer"&gt;https://app.cloudray.io/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A cloud server accessible via SSH:&lt;/strong&gt; If you don’t already have a cloud server, you can get one from popular providers like &lt;a href="https://aws.amazon.com/" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;, &lt;a href="https://www.digitalocean.com/" rel="noopener noreferrer"&gt;DigitalOcean&lt;/a&gt;, and &lt;a href="https://cloud.google.com/" rel="noopener noreferrer"&gt;Google Cloud&lt;/a&gt;. Ensure the server has at least 4GB of RAM, and a minimum of 20GB SSD&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSH credentials:&lt;/strong&gt; Ensure you have access to the necessary SSH keys or login credentials to access your server. If you don’t have an SSH key set up, follow &lt;a href="https://dev.to/docs/server-keys"&gt;this guide&lt;/a&gt; to create one and add it to CloudRay&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The servers are added to CloudRay:&lt;/strong&gt; Before proceeding, make sure your server is connected to CloudRay. If you haven’t done this yet, follow &lt;a href="https://cloudray.io/docs/servers" rel="noopener noreferrer"&gt;this guide&lt;/a&gt; to add and manage your server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;NOTE&lt;/p&gt;

&lt;p&gt;This guide uses Bash scripts, providing a high degree of customisation. You can adapt the scripts to fit your specific Installations needs and environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Assumptions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This guide assumes you’re using &lt;strong&gt;Rocky Linux 9&lt;/strong&gt; as your server’s operating system. If you’re using a different version or a different distribution, adjust the commands accordingly&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create the Automation Script
&lt;/h2&gt;

&lt;p&gt;To automate the installation of Nagios, you’ll need two Bash scripts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Setup Nagios Script:&lt;/strong&gt; Installs the necessary dependencies and configures Nagios Core&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deploy Nagios Script:&lt;/strong&gt; Sets up the web interface, enables Nagios, and configures the firewall&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let’s begin with the setting up of Nagios&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup Nagios Script
&lt;/h3&gt;

&lt;p&gt;To create the Setup Nagios Script, you need to follow these steps:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba9zsnorogvnq8kils7k.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fba9zsnorogvnq8kils7k.jpg" alt="Screenshot of adding a new setup script" width="799" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; in your CloudRay project&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Setup Nagios Script&lt;/code&gt;. You can give it any name of your choice&lt;/li&gt;
&lt;li&gt;Copy this code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Exit on error&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Update system packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf update &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install required dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install tar &lt;/span&gt;nano gcc glibc glibc-common wget perl net-snmp openssl-devel make unzip gd gd-devel epel-release httpd php php-cli php-common php-gd &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Create a directory for Nagios and navigate to it&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~
&lt;span class="nb"&gt;mkdir &lt;/span&gt;nagios
&lt;span class="nb"&gt;cd &lt;/span&gt;nagios

&lt;span class="c"&gt;# Download Nagios Core&lt;/span&gt;
wget https://assets.nagios.com/downloads/nagioscore/releases/nagios-4.5.9.tar.gz

&lt;span class="c"&gt;# Ensure tar is installed&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install tar&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Extract Nagios&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; nagios-4.5.9.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;nagios-4.5.9

&lt;span class="c"&gt;# Configure and compile Nagios&lt;/span&gt;
./configure
make all

&lt;span class="c"&gt;# Create Nagios user and groups&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;make install-groups-users
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="nt"&gt;-G&lt;/span&gt; nagios apache

&lt;span class="c"&gt;# Install Nagios and its components&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nb"&gt;install
sudo &lt;/span&gt;make install-init
&lt;span class="nb"&gt;sudo &lt;/span&gt;make install-commandmode
&lt;span class="nb"&gt;sudo &lt;/span&gt;make install-config
&lt;span class="nb"&gt;sudo &lt;/span&gt;make install-webconf

&lt;span class="c"&gt;# Verify Nagios configuration&lt;/span&gt;
&lt;span class="nb"&gt;sudo&lt;/span&gt; /usr/local/nagios/bin/nagios &lt;span class="nt"&gt;-v&lt;/span&gt; /usr/local/nagios/etc/nagios.cfg

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Nagios core setup completed successfully!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a breakdown of what each command in the &lt;code&gt;Setup Nagios Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Updates all installed packages to the latest version&lt;/li&gt;
&lt;li&gt;Installs essential packages like &lt;code&gt;gcc&lt;/code&gt;, &lt;code&gt;nano&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, &lt;code&gt;perl&lt;/code&gt;, &lt;code&gt;httpd&lt;/code&gt;, and &lt;code&gt;php&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Creates and navigates to a directory for Nagios installation&lt;/li&gt;
&lt;li&gt;Downloads Nagios Core (version 4.5.9 in this case) and Extracts the Nagios archive&lt;/li&gt;
&lt;li&gt;Configures and compiles Nagios&lt;/li&gt;
&lt;li&gt;Creates the &lt;code&gt;nagios&lt;/code&gt; user and group and adds the &lt;code&gt;apache&lt;/code&gt; user to the &lt;code&gt;nagios&lt;/code&gt; group for web interface access&lt;/li&gt;
&lt;li&gt;Install Nagios components, including the core configuration, init scripts, and web interface&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deploy Nagios Script
&lt;/h3&gt;

&lt;p&gt;Next, you need to create the deployment script for Nagios. To do so, follow similar steps as the above:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ulmy6idosg7lvl9pitj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0ulmy6idosg7lvl9pitj.jpg" alt="Screenshot of deploying Nagios" width="800" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Scripts&lt;/strong&gt; &amp;gt; &lt;strong&gt;New Script&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name: &lt;code&gt;Deploy Nagios Script&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add code:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;

&lt;span class="c"&gt;# Exit on error&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="c"&gt;# Create Nagios admin user&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;htpasswd &lt;span class="nt"&gt;-cb&lt;/span&gt; /usr/local/nagios/etc/htpasswd.users &lt;span class="o"&gt;{{&lt;/span&gt;nagios_user&lt;span class="o"&gt;}}&lt;/span&gt; &lt;span class="o"&gt;{{&lt;/span&gt;nagios_password&lt;span class="o"&gt;}}&lt;/span&gt;

&lt;span class="c"&gt;# Set proper permissions&lt;/span&gt;
&lt;span class="nb"&gt;sudo chown &lt;/span&gt;apache:nagios /usr/local/nagios/etc/htpasswd.users

&lt;span class="c"&gt;# Start and enable Nagios&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start nagios
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;nagios

&lt;span class="c"&gt;# Confirm Nagios is running&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl status nagios &lt;span class="nt"&gt;--no-pager&lt;/span&gt;

&lt;span class="c"&gt;# Install and configure FirewallD&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;dnf &lt;span class="nb"&gt;install &lt;/span&gt;firewalld &lt;span class="nt"&gt;-y&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start firewalld
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;firewalld

&lt;span class="c"&gt;# Open HTTP port&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--add-service&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http &lt;span class="nt"&gt;--permanent&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;firewall-cmd &lt;span class="nt"&gt;--reload&lt;/span&gt;

&lt;span class="c"&gt;# Enable and restart services&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;httpd
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nagios httpd

&lt;span class="c"&gt;# Install Nagios plugins&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ~/nagios/
wget https://nagios-plugins.org/download/nagios-plugins-2.4.11.tar.gz
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; nagios-plugins-2.4.11.tar.gz
&lt;span class="nb"&gt;cd &lt;/span&gt;nagios-plugins-2.4.11

./configure
make
&lt;span class="nb"&gt;sudo &lt;/span&gt;make &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Final restart&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart nagios httpd

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Nagios deployment completed successfully!"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what the &lt;code&gt;Deploy Nagios Script&lt;/code&gt; does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a Nagios web admin user with the password&lt;/li&gt;
&lt;li&gt;Ensures Apache and Nagios have the right permissions&lt;/li&gt;
&lt;li&gt;Starts, enables, and checks the status of the Nagios service&lt;/li&gt;
&lt;li&gt;Installs the firewall and opens port 80 for HTTP traffic&lt;/li&gt;
&lt;li&gt;Downloads and installs Nagios plugins for additional monitoring capabilities&lt;/li&gt;
&lt;li&gt;Restarts Nagios and the web server to apply changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Create a Variable Group
&lt;/h2&gt;

&lt;p&gt;Now, before running the scripts, you need to define values for the placeholders &lt;code&gt;{{nagios-user}}&lt;/code&gt;, &lt;code&gt;{{nagios-password}}&lt;/code&gt;, &lt;code&gt;{{nagios-alias}}&lt;/code&gt;, &lt;code&gt;{{nagios-email}}&lt;/code&gt;, &lt;code&gt;{{nagios-server-ip}}&lt;/code&gt;, and &lt;code&gt;{{remote-server-ip}}&lt;/code&gt; used in the scrips. CloudRay processes all scripts as &lt;a href="https://shopify.github.io/liquid/" rel="noopener noreferrer"&gt;Liquid templates&lt;/a&gt;. This allows you to use variables dynamically across different servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8yhy723chcbwpiq2zx7.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm8yhy723chcbwpiq2zx7.jpg" alt="Screenshot of adding a new variable group" width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To ensure that these values are automatically substituted when the script runs, follow these steps to create a variable Group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Variable Groups:&lt;/strong&gt; In your CloudRay project, go to “Scripts” in the top menu and click on “Variable Groups”.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a new Variable Group:&lt;/strong&gt; Click on “Variable Group”.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add the following variables:&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nagios-user&lt;/code&gt;:&lt;/strong&gt; This is the Nagios username&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nagios-password&lt;/code&gt;:&lt;/strong&gt; This is the Nagios password&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nagios-alias&lt;/code&gt;:&lt;/strong&gt; This is the Nagios alias&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nagios-email&lt;/code&gt;:&lt;/strong&gt; The email of the Nagios account&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;nagios-server-ip&lt;/code&gt;:&lt;/strong&gt; The IP Address of the Nagios Server&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;remote-server-ip&lt;/code&gt;:&lt;/strong&gt; The IP Address of the remote server to be monitored&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since the variables are setup, proceed to run the scripts with CloudRay.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running the Scripts to Install Nagios with CloudRay
&lt;/h2&gt;

&lt;p&gt;Now that everything is setup, you can use CloudRay to automate the installation of Nagios.&lt;/p&gt;

&lt;p&gt;You can choose to run the scripts individually or execute them all at once using &lt;a href="https://cloudray.io/docs/script-playlists" rel="noopener noreferrer"&gt;CloudRay’s Script Playlists&lt;/a&gt;. Since there are multiple scripts, using CloudRay playlists will help automate the execution sequence and save time.&lt;/p&gt;

&lt;p&gt;Here are the steps to follow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to “Script Playlists”:&lt;/strong&gt; Click on the Scripts tab in the CloudRay interface
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbrlryxkjcc4ct3xpud39.jpg" alt="Locate the script playlist in CloudRay interface" width="512" height="186"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click “Add Script Playlist”:&lt;/strong&gt; This initiates the creation of a new playlist&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provide a Name:&lt;/strong&gt; Give your playlist a unique name (For example “Nagios Deployment Automation and Management”)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add Scripts in Order:&lt;/strong&gt; Select and add the scripts sequentially
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8da2dbex361a1ei3snc4.jpg" alt="Locate the script playlist in CloudRay interface" width="764" height="442"&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Save the Playlist:&lt;/strong&gt; Click “create playlist” to store your new playlist.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Once your script playlist is created, proceed with execution:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Navigate to Runlogs&lt;/strong&gt; : In your CloudRay project, go to the Runlogs section in the top menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Create a New Runlog&lt;/strong&gt; : Click on New Runlog.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Configure the Runlog&lt;/strong&gt; : Provide the necessary details:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1lr9w4wqu01u2h2ylnft.jpg" alt="Screenshot of creating a new runlog" width="732" height="438"&gt;
&lt;/li&gt;
&lt;li&gt;Server: Select the server where Nagios will be installed&lt;/li&gt;
&lt;li&gt;Script Playlist: Choose the playlist you created (For example “Nagios Deployment Automation and Management”)&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Variable Group: Select the variable group you set up earlier&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Execute the Script&lt;/strong&gt; : Click on &lt;strong&gt;Run Now&lt;/strong&gt; to start the execution&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rqyrihj52ux1noae1x0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2rqyrihj52ux1noae1x0.jpg" alt="Screenshot of the result of all the script from the script playlist" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your Nagios is now seamlessly deployed and managed with CloudRay. That’s it! Happy deploying!. You can access it by visiting &lt;code&gt;http://&amp;lt;nagios-server-ip&amp;gt;/nagios&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;If you encounter issues during deployment, consider the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nagios Web Interface Not Loading:&lt;/strong&gt; Ensure Apache is running with &lt;code&gt;sudo systemctl status httpd&lt;/code&gt; and restart it using &lt;code&gt;sudo systemctl restart httpd&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Nagios Service Not Starting:&lt;/strong&gt; Check the service status with &lt;code&gt;sudo systemctl status nagios&lt;/code&gt; and restart it using &lt;code&gt;sudo systemctl restart nagios&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the issue persists, consult the &lt;a href="https://www.nagios.org/documentation/" rel="noopener noreferrer"&gt;Nagios Core Documentation&lt;/a&gt; for further assistance.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://app.cloudray.io/f/auth/sign-up" rel="noopener noreferrer"&gt;Get Started with CloudRay&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Best Way to Install Docker on Kali Linux</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Wed, 29 Nov 2023 20:34:40 +0000</pubDate>
      <link>https://dev.to/geosegun/best-way-to-install-docker-on-kali-linux-3103</link>
      <guid>https://dev.to/geosegun/best-way-to-install-docker-on-kali-linux-3103</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v6ivii3ea4dpra5xzla.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v6ivii3ea4dpra5xzla.jpg" alt="output" width="427" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  INTRODUCTION
&lt;/h2&gt;

&lt;p&gt;Are you finding it difficult to install Docker on your Linux machine? &lt;br&gt;
Docker is a powerful platform that enables developers to build, ship, and run applications in containers. Installing Docker on Kali can be tasking. Running docker Linux is a straightforward process, and in this guide, we'll walk you through each step, explaining the command line scripts along the way. Let's get started.&lt;/p&gt;
&lt;h2&gt;
  
  
  PREREQUISITES
&lt;/h2&gt;

&lt;p&gt;Before installing docker. it is important to get have the following prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A kali Linux Machine (ensure it is up-to-date)&lt;/li&gt;
&lt;li&gt;Access to the terminal with sudo privileges&lt;/li&gt;
&lt;li&gt;Basic understanding of command line.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To install docker in your kali linux machine, follow these steps:&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1: Update packages List
&lt;/h2&gt;

&lt;p&gt;To start the installation of docker in your machine, it is important to update your package lists. To do this, open your terminal and run the following command to ensure that your package lists are updated:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mjbxg30udew5bs6s1uk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8mjbxg30udew5bs6s1uk.png" alt="output" width="682" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install Docker
&lt;/h2&gt;

&lt;p&gt;Once the package lists are successfully installed, install Docker using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt install docker.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gtzbzza38mt1mtmo1zy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9gtzbzza38mt1mtmo1zy.png" alt="output" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Enable and Start Docker Services
&lt;/h2&gt;

&lt;p&gt;Docker requires a service to be running in the background. This steps enables and start the docker service with the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable docker --now
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybxhwlmwrge1mhf8y612.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fybxhwlmwrge1mhf8y612.png" alt="output" width="800" height="76"&gt;&lt;/a&gt;&lt;br&gt;
This command not only enables Docker to start on boot but also starts the service immediately.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4: Check Docker Service Status
&lt;/h2&gt;

&lt;p&gt;To ensure docker is up and running, it is important to check the status. Use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbyd7oliaj3kvri4qnea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frbyd7oliaj3kvri4qnea.png" alt="output" width="800" height="396"&gt;&lt;/a&gt;&lt;br&gt;
This command provides detailed information about the Docker service, including its current status. Look for &lt;strong&gt;Active&lt;/strong&gt; to confirm that Docker is running.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Add Your User to the Docker Group
&lt;/h2&gt;

&lt;p&gt;This step is required to avoid &lt;code&gt;sudo&lt;/code&gt; each time you want to use Docker, add your user to the Docker group:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo usermod -aG docker $USER
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step grants your user the necessary permissions to interact with the Docker daemon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Restart Your System
&lt;/h2&gt;

&lt;p&gt;To apply the changes made by adding your user to the Docker group, restart your system. You can do this by signing out and signing back in or using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo reboot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Verify Docker Installation
&lt;/h2&gt;

&lt;p&gt;Confirm that Docker is successfully installed by checking its version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ck15zhyk2lbmvpjixi7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5ck15zhyk2lbmvpjixi7.png" alt="output" width="386" height="132"&gt;&lt;/a&gt;&lt;br&gt;
This command displays the installed Docker version, confirming that the installation was successful.&lt;/p&gt;

&lt;h2&gt;
  
  
  CONCLUSION
&lt;/h2&gt;

&lt;p&gt;Congratulations on successfully navigating through the installation of Docker on your Kali Linux machine! Docker brings a new level of flexibility and efficiency to your development and deployment workflows. With containers, you can ensure consistency across different environments, making your life as a developer much smoother. Feel free to explore Docker's vast capabilities and revolutionize the way you package and deploy applications.&lt;br&gt;
Happy coding!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>opensource</category>
      <category>docker</category>
      <category>linux</category>
    </item>
    <item>
      <title>A Beginner's Guide: Installing MongoDB on Ubuntu 🔥 in 5 Simple Steps 🚀</title>
      <dc:creator>rising_segun</dc:creator>
      <pubDate>Wed, 13 Sep 2023 21:04:28 +0000</pubDate>
      <link>https://dev.to/geosegun/a-beginners-guide-installing-mongodb-on-ubuntu-in-5-simple-steps-1n7f</link>
      <guid>https://dev.to/geosegun/a-beginners-guide-installing-mongodb-on-ubuntu-in-5-simple-steps-1n7f</guid>
      <description>&lt;p&gt;Looking for a Hassle-Free MongoDB Installation on Ubuntu? Your search ends here! Follow this comprehensive step-by-step guide to effortlessly set up your MongoDB database on any Ubuntu or Linux-based system.&lt;/p&gt;

&lt;p&gt;By the end of this article, you’ll have mastered installing MongoDB on Ubuntu effortlessly. This comprehensive guide not only offers a step-by-step walkthrough but also delves into the tools and techniques, providing valuable insights for seamless execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;To successfully install MongoDB on your Linux-based system, the following must be done:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;knowledge of MongoDB&lt;/li&gt;
&lt;li&gt;A general knowledge of working with command line/shell commands&lt;/li&gt;
&lt;li&gt;Ubuntu or other Linux-based operating systems on the host workstation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to Install MongoDB on Ubuntu
&lt;/h2&gt;

&lt;p&gt;MongoDB installation on Ubuntu is a simple process that allows you to set up a powerful and versatile NoSQL database on your system. By following a few simple steps, you can have MongoDB up and running in no time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Import MongoDB Repositories
&lt;/h3&gt;

&lt;p&gt;It is important&amp;nbsp;to ensure the legitimacy and integrity of the packages when installing MongoDB on Ubuntu. Ubuntu's Package Management system uses GPG keys to validate package signatures, adding an&amp;nbsp;extra layer of&amp;nbsp;security. To begin the MongoDB installation, you must first import the MongoDB Public GPG key into your Ubuntu system. The MongoDB Public GPG key can be imported with the following terminal command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a Source list for your MongoDB installation next. To accomplish this, use the following command to create the &lt;code&gt;"/etc/apt/sources.list.d/mongodb-org-3.4.list"&lt;/code&gt; list file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "deb http://repo.mongodb.org/apt/ubuntu xenial/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With your list file now created, you can install the Local Package repository. To do this, you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Installing MongoDB Packages
&lt;/h3&gt;

&lt;p&gt;You now need to install the latest stable version of MongoDB on your system. Use the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install -y mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you wish to install a certain version of MongoDB on your system, you must specify the version for each component package when you install it. For example, installing a specific version. run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-get install -y mongodb-org=3.4 mongodb-org-server=3.4 mongodb-org-shell=3.4 mongodb-org-mongos=3.4 mongodb-org-tools=3.4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Launching MongoDB as a Service on Ubuntu
&lt;/h3&gt;

&lt;p&gt;Now that MongoDB is up and running, you must build a Unit file to assist your system in understanding the resource management process. For example, the most widely used Unit file determines how to start, stop, or manage a service automatically.&lt;br&gt;
To do this, you can create a configuration file, &lt;code&gt;“mongodb.service in /etc/systemd/system”&lt;/code&gt;, that will help manage the MongoDB system.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vim /etc/systemd/system/mongodb.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, copy the following information in your configuration file:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt1kpg20uyzhi5l5mauc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzt1kpg20uyzhi5l5mauc.png" alt="config file" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that the configuration file has been produced, use the following command to update the system service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, start the updated systemd service for your MongoDB instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the instance&amp;nbsp;is running, check to see if MongoDB launched on port 27017. To accomplish this, use the "netstat" command as&amp;nbsp;follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;netstat -plntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To confirm if your MongoDB instance started successfully, you need to use the status command as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you can now enable auto-start functionality for your system as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl enable mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an instance you want to start or restart the MongoDB instance running on your Ubuntu installation, run the below commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl stop mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Configuring and Connecting MongoDB
&lt;/h3&gt;

&lt;p&gt;From the above steps, we have successfully installed MongoDB service. This step shows how to install MongoDB. To do this, open the Mongo Shell and switch to the database admin mode using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongo
use admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, create a root user for your MongoDB installation and exit the Mongo Shell as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;db.createUser({user:"admin", pwd:”password", roles:[{role:"root", db:"admin"}]})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: you can replace the user and pwd with your preferred choice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;with this setup, you can now connect with your MongoDB, by first restarting MongoDB and then using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mongo -u admin -p admin123 --authenticationDatabase admin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you’ll now be able to see MongoDB set up a connection. You can use the “show dbs” command as follows to open a list of all available databases. With all these, you’ve successfully installed MongoDB on Ubuntu.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: MongoDB Tuning
&lt;/h3&gt;

&lt;p&gt;Scaling MongoDB is simple and may be done horizontally or vertically. This is critical for the Database's optimal performance. Horizontal scaling involves the addition of server resources such as RAM and CPUs, whereas vertical scaling involves the addition of servers to the configuration. Several factors influence the performance of the MongoDB Database, including memory usage, the number of concurrent connections, and the WiredTiger Cache, among others. MongoDB's default storage engine is WiredTiger, which saves 50% of RAM. This indicates that 8GB of RAM will have a memory preserver of 0.5*(8-1) for WiredTiger. Use the following command to check use statistics and determine whether modifications are needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jtk6kpwtie4ouz84n4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9jtk6kpwtie4ouz84n4i.png" alt="tuning" width="800" height="924"&gt;&lt;/a&gt;&lt;br&gt;
From the above result, some of the key points to note are listed below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wiredTiger.cache.maximum bytes configure&lt;/li&gt;
&lt;li&gt;wiredTiger.cache.bytes currently in the cache&lt;/li&gt;
&lt;li&gt;wiredTiger.cache.pages read into cache&lt;/li&gt;
&lt;li&gt;wiredTiger.cache.pages written from cache&lt;/li&gt;
&lt;li&gt;wiredTiger.cache.tracked dirty bytes in the cache&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To check the usage of WiredTiger Concurrency Read and Write Ticket, follow the command given below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz9jb0b0i4evgkafbky1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz9jb0b0i4evgkafbky1.png" alt="db" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In just 5 straightforward steps, you've embarked on a journey to harness the power of MongoDB on your Ubuntu system. By following this beginner's guide, you've not only successfully installed MongoDB but also gained valuable insights into managing databases on Linux.&lt;br&gt;
With MongoDB in your toolkit, you're well-equipped to handle diverse data needs and build robust applications. So, go ahead and explore the endless possibilities this NoSQL database offers. Whether you're a developer, a data enthusiast, or a tech enthusiast, MongoDB on Ubuntu is your gateway to efficient data management.&lt;br&gt;
Start your MongoDB adventure today and witness your projects scale and thrive like never before!"&lt;/p&gt;

</description>
      <category>devops</category>
      <category>mongodb</category>
      <category>database</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
