{"id":13,"date":"2026-08-28T04:32:31","date_gmt":"2026-08-28T04:32:31","guid":{"rendered":"https:\/\/newsmagazinexpro.kinsta.cloud\/demo\/?p=13"},"modified":"2026-10-03T12:04:09","modified_gmt":"2026-10-03T12:04:09","slug":"deploy-node-js-apps-shared-web-hosting","status":"publish","type":"post","link":"https:\/\/www.firevm.com\/blog\/deploy-node-js-apps-shared-web-hosting\/","title":{"rendered":"Deploy Node.js apps on Shared Web Hosting"},"content":{"rendered":"\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\"><strong>TL;DR:<\/strong> Most shared hosting plans can&#8217;t run a modern Node.js app. There&#8217;s no build pipeline, no process manager, and no way to run <code>npm install<\/code> without SSH access. <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.firevm.com\/web-hosting\/\">FireVM&#8217;s shared hosting<\/a> changes that, no terminal, no command line.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">In this guide, we&#8217;ll deploy <strong>TailAdmin<\/strong>, a free Next.js admin dashboard, entirely through the browser using the FireVM control panel. Next.js runs on Node.js, so this walkthrough doubles as a real-world demo of the server&#8217;s <strong>Node.js capability<\/strong>: a full build pipeline, npm, and live process management, not just a static site.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Why Node.js is usually a pain on shared hosting<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Most shared hosting plans weren&#8217;t built with Node.js in mind. There&#8217;s no way to run a build, no process manager to keep your app alive, and no sane way to deploy changes without SSH.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s what that typically looks like, compared to running Node.js on FireVM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">On most shared hosts (what usually goes wrong)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>No Node.js runtime exposed through the panel at all, or it&#8217;s bolted on as a CGI\/FastCGI hack<\/li>\n\n\n\n<li>No <code>npm install<\/code> or build step without shell access<\/li>\n\n\n\n<li>Apps served through a request-based proxy that restarts on every request, so long-lived connections and WebSockets don&#8217;t work<\/li>\n\n\n\n<li>No process manager, so a crashed app just stays down until someone notices<\/li>\n\n\n\n<li>Git deploys mean manually pulling and rebuilding over SSH every time<\/li>\n\n\n\n<li>Environment variables set by hand, often lost on redeploy<\/li>\n\n\n\n<li>Node.js support, where it exists at all, usually means paying several times the cost of shared hosting for a VPS<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">On FireVM shared hosting (everything else, taken care of)<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Node.js runs as a real, persistent process, not a proxy hack that restarts<\/li>\n\n\n\n<li><code>npm install<\/code> and build scripts run directly from the panel, no shell needed<\/li>\n\n\n\n<li>Git-based deploys with configurable post-deploy actions, push and it builds<\/li>\n\n\n\n<li>Application startup file and environment variables managed from a dashboard<\/li>\n\n\n\n<li>WebSockets and long-held connections work properly since the process stays alive<\/li>\n\n\n\n<li>SSH access is included too, if you&#8217;d rather work from the terminal<\/li>\n\n\n\n<li>All of this runs on the same shared hosting plan, no VPS required<\/li>\n<\/ul>\n\n\n\n<h1 class=\"wp-block-heading\">Watch it happen, then do it yourself<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s a full walkthrough deploying the TailAdmin demo app, a real Next.js app with an admin dashboard, sample data, and charts, done entirely in the browser.<\/p>\n\n\n\n<figure class=\"wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio\"><div class=\"wp-block-embed__wrapper\">\n<iframe loading=\"lazy\" title=\"Deploy Next.js in 20 Minutes on FireVM Shared Hosting (No SSH, Just Web UI)\" width=\"960\" height=\"540\" src=\"https:\/\/www.youtube.com\/embed\/jjYsSw-j4_g?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" referrerpolicy=\"strict-origin-when-cross-origin\" allowfullscreen><\/iframe>\n<\/div><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Watch this 5-minute walkthrough:<\/strong> Deploying TailAdmin on Next.js to FireVM shared hosting. The real setup takes about 20 minutes, most of it is just &#8220;build&#8221; wait-time.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The steps below follow the exact same sequence shown in the video above, so you can follow along side by side if you&#8217;d rather watch than read. If you&#8217;d rather work from an SSH terminal instead of the Web UI, that&#8217;s covered too, right after the UI-based walkthrough.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Installing TailAdmin, step by step<\/h1>\n\n\n\n<h2 class=\"wp-block-heading\">Step 1: Prepare the Subdomain<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Create the subdomain<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In the FireVM panel, go to <strong>Domains \u2192 Add a Subdomain<\/strong>. Give it a name (we&#8217;re using <code>app<\/code>) and confirm the document root, which the FireVM control panel sets automatically based on the subdomain name. This walkthrough uses a subdomain, but the same steps work just as well on a full domain name, if that&#8217;s what your project needs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enable SSL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open <strong>Hosting Settings<\/strong> for the new subdomain and find <strong>SSL\/TLS support<\/strong>. Enable it, then select your existing Let&#8217;s Encrypt certificate from the Certificate dropdown. Save.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Remove the default index file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When a subdomain is created, the FireVM control panel drops a placeholder <code>index.html<\/code> file into its root. <strong>If you don&#8217;t delete this, it will load instead of your app once deployed.<\/strong> Open File Manager for the subdomain and delete <code>index.html<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enable Node.js<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">On the subdomain&#8217;s <strong>Get Started<\/strong> tab, click <strong>Node.js<\/strong>, then <strong>Enable Node.js<\/strong>. This turns on Node support for the subdomain and gives you access to the Node.js dashboard.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This gives you access to the Node.js dashboard for the subdomain, where the rest of the deployment settings live.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 2: Deploy the App via Git<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Connect the repository<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">From the Get Started tab, click <strong>Deploy using Git<\/strong>. Choose <strong>Remote repository<\/strong>, since the code lives on GitHub rather than your own machine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Enter the repository URL:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>https:&#47;&#47;github.com\/TailAdmin\/free-nextjs-admin-dashboard.git<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Set <strong>Deployment mode<\/strong> to Automatic, and confirm the <strong>Server path<\/strong> matches your subdomain&#8217;s directory.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Add the deploy actions<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Check <strong>Enable additional deployment actions<\/strong> and paste in the following commands, one per line:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install\nnpm run build\ncp -r public .next\/standalone\/\ncp -r .next\/static .next\/standalone\/.next\/<\/code><\/pre>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">This step can take a <strong>couple of minutes<\/strong> to finish. Wait for the console to confirm completion rather than assuming it&#8217;s done.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">These install dependencies, build the app, and copy the static assets into place for the standalone output Next.js produces. Click <strong>Create<\/strong>. This pulls the repository files but doesn&#8217;t trigger a full deployment yet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 3: Edit the Config Files<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Two small edits are needed before the production build will work correctly.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Automate the post-build step<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open <code>package.json<\/code> in File Manager&#8217;s code editor and add a <code>postbuild<\/code> script:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"postbuild\": \"cp -r public .next\/standalone\/ &amp;&amp; cp -r .next\/static .next\/standalone\/.next\/ &amp;&amp; mkdir -p tmp &amp;&amp; touch tmp\/restart.txt\",<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This copies the static assets automatically after every build and touches a restart file, so Passenger picks up the change without a manual restart.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set standalone output<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Open <code>next.config.ts<\/code> and add this line inside the config object:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>output: 'standalone',<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This tells Next.js to bundle a self-contained server file, so Passenger can run the app directly instead of needing Next&#8217;s own dev server.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 4: Run the Production Build<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Go to the Node.js dashboard and click <strong>Run script<\/strong>. Type <code>build<\/code> as the script name and click <strong>Run<\/strong>.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p class=\"wp-block-paragraph\">This step can take up to <strong>10 minutes<\/strong>. The console may appear to hang with no visible output during that time, that&#8217;s normal, let it run while you sip some coffee \ud83d\ude42<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If nothing has happened after 20 minutes, something has likely gone wrong, a frozen browser tab or a network glitch are common culprits. In that case, click <strong>Run script<\/strong> again to restart the build from scratch.<\/p>\n<\/blockquote>\n\n\n\n<p class=\"wp-block-paragraph\">This compiles the app into optimized static and server files, and the postbuild script you added in Step 3 runs automatically right after, copying the assets into place.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Step 5: Set the Startup File and Launch<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Passenger is what actually runs your Node.js app behind the scenes, and by default it looks for a file called <code>app.js<\/code>, which doesn&#8217;t exist in a standalone Next.js build. Go back to the Node.js dashboard, open <strong>Application Startup File<\/strong>, and set it to:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>.next\/standalone\/server.js<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Click <strong>OK<\/strong>, then <strong>Restart App<\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Launch the app<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Visit your subdomain, for example <a href=\"https:\/\/app.inspirevilla.com\">https:\/\/app.inspirevilla.com<\/a>. TailAdmin should now be live, fully deployed through the browser with no SSH session ever opened.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo.png\" target=\"_blank\" rel=\" noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"532\" src=\"https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo-1024x532.png\" alt=\"Tailadmin demo\" class=\"wp-image-565\" style=\"box-shadow:var(--wp--preset--shadow--natural)\" srcset=\"https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo-1024x532.png 1024w, https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo-300x156.png 300w, https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo-768x399.png 768w, https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo-1536x798.png 1536w, https:\/\/www.firevm.com\/blog\/wp-content\/uploads\/2025\/01\/tailadmin-demo.png 1919w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h1 class=\"wp-block-heading\">Prefer the terminal? Here&#8217;s the SSH version<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">Everything above runs through FireVM&#8217;s control panel UI, but Developer and above plans include full SSH access too. If you&#8217;d rather work from the terminal, here&#8217;s the same install as a command sequence. The UI version handles a few things automatically behind the scenes, like restarting the app after a rebuild, so the SSH version adds a couple of extra steps to cover that manually.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># 1. Navigate to your subdomain's document root\ncd ~\/app.inspirevilla.com\n\n# 2. Clone the TailAdmin repo directly into this folder\ngit clone https:\/\/github.com\/TailAdmin\/free-nextjs-admin-dashboard.git .\n\n# 3. Install npm dependencies\nnpm install\n\n# 4. Edit package.json to add the postbuild script\nnano package.json\n# add: \"postbuild\": \"cp -r public .next\/standalone\/ &amp;&amp; cp -r .next\/static .next\/standalone\/.next\/ &amp;&amp; mkdir -p tmp &amp;&amp; touch tmp\/restart.txt\",\n\n# 5. Edit next.config.ts to enable standalone output\nnano next.config.ts\n# add inside the config object: output: 'standalone',\n\n# 6. Build the app\nnpm run build\n\n# 7. Set the correct Node.js startup file via the panel\n# Application Startup File: .next\/standalone\/server.js\n\n# 8. Tell Passenger to reload the app\ntouch tmp\/restart.txt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Double-check your document root path and Node.js version before running this, both are specific to your setup.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">What&#8217;s next<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">FireVM&#8217;s <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.firevm.com\/web-hosting\/\">Developer plan<\/a> runs Node.js apps like this. Anything below that won&#8217;t give you Git deploys, npm, or process management for Node.js apps.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you&#8217;re running client sites rather than just your own, the <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.firevm.com\/web-hosting\/\">Agency plan<\/a> is the better fit. It gives each client their own isolated account with a separate login, so you can hand off access without exposing anything else on your hosting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If your app genuinely needs more than shared web hosting can offer, heavier traffic, custom server-level configuration, or full root access, <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.firevm.com\/vps-hosting\/\">FireVM&#8217;s VPS hosting<\/a> is there too. And if you ever outgrow VPS as well, <a target=\"_blank\" rel=\"noopener\" href=\"https:\/\/www.firevm.com\/dedicated-servers\/\">FireVM&#8217;s dedicated servers<\/a> are there for when you need a machine entirely to yourself.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>TL;DR: Most shared hosting plans can&#8217;t run a modern Node.js app. There&#8217;s no build pipeline, no process manager, and no way to run npm install without SSH access. FireVM&#8217;s shared hosting changes that, no terminal, no command line. In this guide, we&#8217;ll deploy TailAdmin, a free Next.js admin dashboard, entirely through the browser using the<\/p>\n","protected":false},"author":1,"featured_media":567,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[11,14],"class_list":["post-13","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-guides","tag-editors-pick","tag-featured"],"_links":{"self":[{"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/posts\/13","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/comments?post=13"}],"version-history":[{"count":3,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions"}],"predecessor-version":[{"id":581,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/posts\/13\/revisions\/581"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/media\/567"}],"wp:attachment":[{"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/media?parent=13"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/categories?post=13"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.firevm.com\/blog\/wp-json\/wp\/v2\/tags?post=13"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}