<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Strapi &#8211; CJSelvamani</title>
	<atom:link href="https://cjselvamani.com/tag/strapi/feed/" rel="self" type="application/rss+xml" />
	<link>https://cjselvamani.com</link>
	<description>Saved by Gracious Faith Alone</description>
	<lastBuildDate>Wed, 01 Apr 2026 13:30:54 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>How to Set Up Strapi on cPanel Using Phusion Passenger</title>
		<link>https://cjselvamani.com/how-to-set-up-strapi-on-cpanel-using-phusion-passenger/</link>
					<comments>https://cjselvamani.com/how-to-set-up-strapi-on-cpanel-using-phusion-passenger/#respond</comments>
		
		<dc:creator><![CDATA[cjselvamani]]></dc:creator>
		<pubDate>Wed, 01 Apr 2026 10:46:15 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[cPanel]]></category>
		<category><![CDATA[Phusion Passenger]]></category>
		<category><![CDATA[Strapi]]></category>
		<guid isPermaLink="false">https://cjselvamani.com/?p=951</guid>

					<description><![CDATA[Deploying Strapi on cPanel with Phusion Passenger is possible, but there are a few details [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Deploying Strapi on cPanel with Phusion Passenger is possible, but there are a few details that matter, especially if your project uses TypeScript. This guide walks through a working production setup for Strapi on cPanel.</p>



<h2 class="wp-block-heading">What You Need</h2>



<p>Before starting, make sure your hosting environment has:</p>



<ul class="wp-block-list">
<li>cPanel Application Manager enabled</li>



<li>Phusion Passenger enabled</li>



<li>Node.js 20+ available</li>



<li>MySQL or MariaDB available</li>



<li>SSH access to the cPanel account</li>



<li>a subdomain for Strapi, for example cms.yourdomain.com</li>
</ul>



<p>A good setup is:</p>



<ul class="wp-block-list">
<li>frontend: https://yourdomain.com</li>



<li>Strapi CMS: https://cms.yourdomain.com</li>
</ul>



<h2 class="wp-block-heading">1. Create the Subdomain</h2>



<p>In cPanel, create a subdomain for Strapi, for example:</p>



<ul class="wp-block-list">
<li>cms.yourdomain.com</li>
</ul>



<p>This is the public URL your Strapi app will use.</p>



<h2 class="wp-block-heading">2. Upload the Strapi Project</h2>



<p>Upload your Strapi app files to the server.</p>



<p>A typical location is:</p>



<ul class="wp-block-list">
<li>/home/yourcpaneluser/public_html</li>
</ul>



<p>or better:</p>



<ul class="wp-block-list">
<li>/home/yourcpaneluser/strapi</li>
</ul>



<p>If you use&nbsp;public_html, make sure your Node app in Application Manager points there.</p>



<p>Upload these parts of the project:</p>



<ul class="wp-block-list">
<li>package.json</li>



<li>package-lock.json</li>



<li>config/</li>



<li>database/</li>



<li>src/</li>



<li>public/</li>



<li>types/</li>



<li>tsconfig.json</li>



<li>favicon.png</li>
</ul>



<p>Do not upload:</p>



<ul class="wp-block-list">
<li>node_modules/</li>



<li>.cache/</li>



<li>temporary build artifacts you do not need</li>
</ul>



<h2 class="wp-block-heading">3. Create the Database</h2>



<p>In cPanel, create a MySQL database and user.</p>



<p>Use the real cPanel-generated names, which are often prefixed. For example:</p>



<ul class="wp-block-list">
<li>database name: youruser_db</li>



<li>username: youruser_user</li>
</ul>



<p>Do not assume local placeholder names like&nbsp;strapi_fold&nbsp;will work in production.</p>



<h2 class="wp-block-heading">4. Create the&nbsp;.env&nbsp;File</h2>



<p>In your Strapi app root, create&nbsp;.env&nbsp;with production values:</p>



<pre class="wp-block-code"><code>HOST=0.0.0.0
PORT=1337
NODE_ENV=production
PUBLIC_URL=https://cms.yourdomain.com

APP_KEYS=your_key_1,your_key_2,your_key_3,your_key_4
API_TOKEN_SALT=your_api_token_salt
ADMIN_JWT_SECRET=your_admin_jwt_secret
TRANSFER_TOKEN_SALT=your_transfer_token_salt
ENCRYPTION_KEY=your_encryption_key
JWT_SECRET=your_jwt_secret

DATABASE_CLIENT=mysql
DATABASE_HOST=localhost
DATABASE_PORT=3306
DATABASE_NAME=your_real_db_name
DATABASE_USERNAME=your_real_db_user
DATABASE_PASSWORD=your_real_db_password
DATABASE_SSL=false</code></pre>



<h2 class="wp-block-heading">5. Make Sure&nbsp;server.ts&nbsp;Uses the Public URL</h2>



<p>In&nbsp;config/server.ts, include:</p>



<pre class="wp-block-code"><code>import type { Core } from '@strapi/strapi';

const config = ({ env }: Core.Config.Shared.ConfigParams): Core.Config.Server => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  url: env('PUBLIC_URL', ''),
  app: {
    keys: env.array('APP_KEYS'),
  },
});

export default config;</code></pre>



<p>This makes Strapi use the real public domain instead of&nbsp;localhost.</p>



<h2 class="wp-block-heading">6. Important: Add JS Config Files for Passenger</h2>



<p>If your Strapi project uses TypeScript, Passenger startup via&nbsp;app.js&nbsp;may ignore&nbsp;.ts&nbsp;config files.</p>



<p>You should create JS equivalents in&nbsp;config/:</p>



<ul class="wp-block-list">
<li>config/admin.js</li>



<li>config/api.js</li>



<li>config/database.js</li>



<li>config/middlewares.js</li>



<li>config/plugins.js</li>



<li>config/server.js</li>
</ul>



<p>Example&nbsp;config/admin.js:</p>



<pre class="wp-block-code"><code>module.exports = ({ env }) => ({
  auth: {
    secret: env('ADMIN_JWT_SECRET'),
  },
  apiToken: {
    salt: env('API_TOKEN_SALT'),
  },
  transfer: {
    token: {
      salt: env('TRANSFER_TOKEN_SALT'),
    },
  },
  secrets: {
    encryptionKey: env('ENCRYPTION_KEY'),
  },
  flags: {
    nps: env.bool('FLAG_NPS', true),
    promoteEE: env.bool('FLAG_PROMOTE_EE', true),
  },
});
</code></pre>



<p>Example config/server.js:<br></p>



<pre class="wp-block-code"><code>module.exports = ({ env }) => ({
  host: env('HOST', '0.0.0.0'),
  port: env.int('PORT', 1337),
  url: env('PUBLIC_URL', ''),
  app: {
    keys: env.array('APP_KEYS'),
  },
});
</code></pre>



<p>Example config/api.js:<br></p>



<pre class="wp-block-code"><code>module.exports = {
  rest: {
    defaultLimit: 25,
    maxLimit: 100,
    withCount: true,
  },
};
</code></pre>



<p>Example config/middlewares.js:<br></p>



<pre class="wp-block-code"><code>module.exports = &#91;
  'strapi::logger',
  'strapi::errors',
  'strapi::security',
  'strapi::cors',
  'strapi::poweredBy',
  'strapi::query',
  'strapi::body',
  'strapi::session',
  'strapi::favicon',
  'strapi::public',
];
</code></pre>



<p>Example config/plugins.js:<br></p>



<pre class="wp-block-code"><code>module.exports = ({ env }) => ({});
</code></pre>



<h2 class="wp-block-heading">7. Add&nbsp;app.js&nbsp;for Passenger</h2>



<p>This is the most important file for Passenger.</p>



<p>Create&nbsp;app.js&nbsp;in the app root:</p>



<pre class="wp-block-code"><code>process.env.NODE_ENV = process.env.NODE_ENV || "production";

require("@strapi/strapi")
  .createStrapi({ distDir: "./dist" })
  .start();
</code></pre>



<p>The&nbsp;distDir&nbsp;part matters for serving the built admin frontend correctly.</p>



<h2 class="wp-block-heading">8. Install Dependencies</h2>



<p>SSH into the cPanel account and go to the app folder:</p>



<pre class="wp-block-code"><code>cd ~/public_html
</code></pre>



<p>or wherever your app lives, then run:</p>



<pre class="wp-block-code"><code>/opt/cpanel/ea-nodejs22/bin/npm install
</code></pre>



<p>If your project includes better-sqlite3 but you are using MySQL in production, remove better-sqlite3 first. It often fails to compile on shared hosting and is not needed for MySQL.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>On this cPanel server,&nbsp;npm&nbsp;was not available from the default shell path. Using&nbsp;/opt/cpanel/ea-nodejs22/bin/npm&nbsp;runs the cPanel-provided npm binary directly, which is why it worked.</p>
</blockquote>



<h2 class="wp-block-heading">9. Build Strapi</h2>



<p>Run:</p>



<pre class="wp-block-code"><code>/opt/cpanel/ea-nodejs22/bin/npm run build
</code></pre>



<p>This builds the admin panel.</p>



<h2 class="wp-block-heading">10. Configure cPanel Application Manager</h2>



<p>In cPanel Application Manager, create the Node app with values like:</p>



<ul class="wp-block-list">
<li>Application Name: Strapi</li>



<li>Deployment Domain: cms.yourdomain.com</li>



<li>Base Application URL: /</li>



<li>Application Path: public_html or strapi</li>



<li>Deployment Environment: Production</li>



<li>Startup file: app.js</li>
</ul>



<p>Important:</p>



<ul class="wp-block-list">
<li>Base Application URL should be /</li>



<li>Application Path should be relative to your home directory</li>
</ul>



<h2 class="wp-block-heading">11. Restart the App</h2>



<p>After saving the app in Application Manager, restart it from cPanel.</p>



<p>Do not rely only on manually running&nbsp;node app.js&nbsp;in SSH. Passenger must be the one managing the app process.</p>



<h2 class="wp-block-heading">12. Test the Deployment</h2>



<p>Check:</p>



<ul class="wp-block-list">
<li>https://cms.yourdomain.com/api</li>



<li>https://cms.yourdomain.com/admin</li>



<li>https://cms.yourdomain.com/admin/init</li>
</ul>



<p>If&nbsp;/api&nbsp;returns Strapi JSON and&nbsp;/admin/init&nbsp;returns admin config data, the backend is working.</p>



<h2 class="wp-block-heading">Common Issues</h2>



<h3 class="wp-block-heading">strapi: command not found</h3>



<p>This means&nbsp;npm install&nbsp;did not complete successfully.</p>



<h3 class="wp-block-heading">better-sqlite3&nbsp;build errors</h3>



<p>Remove&nbsp;better-sqlite3&nbsp;if you are using MySQL.</p>



<h3 class="wp-block-heading">Missing admin.auth.secret configuration</h3>



<p>This usually means your&nbsp;.ts&nbsp;config files are not being loaded by Passenger. Add JS config files.</p>



<h3 class="wp-block-heading">/api&nbsp;works but&nbsp;/admin&nbsp;is Not Found</h3>



<p>This usually means your&nbsp;app.js&nbsp;is missing:</p>



<pre class="wp-block-code"><code>.createStrapi({ distDir: "./dist" })
</code></pre>



<h3 class="wp-block-heading">Not Found&nbsp;even when the app is stopped</h3>



<p>That usually means Passenger is not actually serving the subdomain. Recheck Application Manager routing.</p>



<h2 class="wp-block-heading">Final Result</h2>



<p>Once everything is correct, Strapi should work at:</p>



<ul class="wp-block-list">
<li>https://cms.yourdomain.com</li>



<li>admin: https://cms.yourdomain.com/admin</li>
</ul>



<h2 class="wp-block-heading">Closing Notes</h2>



<p>Strapi on cPanel with Passenger works, but TypeScript-based Strapi projects need extra care because Passenger startup does not naturally use&nbsp;.ts&nbsp;config files. The clean solution is to keep your project as-is, but add JS config equivalents and a proper Passenger&nbsp;app.js.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://cjselvamani.com/how-to-set-up-strapi-on-cpanel-using-phusion-passenger/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
