{"id":476,"date":"2025-08-27T22:48:23","date_gmt":"2025-08-27T22:48:23","guid":{"rendered":"https:\/\/1v0.net\/blog\/?p=476"},"modified":"2025-08-27T22:48:25","modified_gmt":"2025-08-27T22:48:25","slug":"how-to-deploy-laravel-12-on-cpanel-hosting","status":"publish","type":"post","link":"https:\/\/1v0.net\/blog\/how-to-deploy-laravel-12-on-cpanel-hosting\/","title":{"rendered":"How to Deploy Laravel 12 on cPanel Hosting"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\"><strong>How to Deploy Laravel 12 on cPanel Hosting<\/strong><\/h2>\n\n\n\n<p>Not every project requires a VPS or cloud infrastructure. Many developers still rely on <strong>cPanel hosting<\/strong> for simplicity and cost-effectiveness. Deploying a Laravel 12 application on cPanel comes with its own challenges: shared servers, no SSH access in some cases, and the need to configure the <code>public\/<\/code> folder properly. In this guide, we\u2019ll walk through a step-by-step approach to get your Laravel app running on a cPanel server with HTTPS, correct file permissions, and a clean URL structure.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>1 \u2014 Prepare Your Laravel Project<\/strong><\/h2>\n\n\n\n<p>Before uploading your application to cPanel, make sure you\u2019ve run composer and built your frontend assets locally:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># From your local machine<\/span>\ncomposer install --optimize-autoloader --no-dev\nnpm install &amp;&amp; npm run build\nphp artisan config:cache\nphp artisan route:cache\nphp artisan view:cache\nphp artisan migrate --force<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures your dependencies are installed, caches are built for performance, and your migrations are ready. Running <code>--no-dev<\/code> keeps unnecessary dev packages out of production.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>2 \u2014 Upload to cPanel<\/strong><\/h2>\n\n\n\n<p>Most cPanel providers give you FTP or File Manager access. You should upload your entire Laravel project, but place the <code>public\/<\/code> folder\u2019s contents into the <code>public_html<\/code> directory.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\"><span class=\"hljs-comment\"># Example structure after upload<\/span>\n\/home\/username\/\n  \u251c\u2500\u2500 laravel-app\/        <span class=\"hljs-comment\"># all Laravel files here<\/span>\n  \u2502   \u251c\u2500\u2500 app\/\n  \u2502   \u251c\u2500\u2500 bootstrap\/\n  \u2502   \u251c\u2500\u2500 config\/\n  \u2502   \u2514\u2500\u2500 ...\n  \u2514\u2500\u2500 public_html\/        <span class=\"hljs-comment\"># cPanel web root<\/span>\n      \u251c\u2500\u2500 index.php       <span class=\"hljs-comment\"># replaced with Laravel's public\/index.php<\/span>\n      \u251c\u2500\u2500 css\/\n      \u251c\u2500\u2500 js\/\n      \u2514\u2500\u2500 ...<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Instead of uploading the whole <code>public\/<\/code> folder, move its contents into <code>public_html<\/code>. Then, edit <code>public\/index.php<\/code> to point to the correct paths for <code>autoload.php<\/code> and <code>app.php<\/code>.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>3 \u2014 Update Index.php Paths<\/strong><\/h2>\n\n\n\n<p>After moving files, update the paths inside <code>public_html\/index.php<\/code> so they point to the correct directory:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-comment\">\/\/ public_html\/index.php<\/span>\n\n<span class=\"hljs-keyword\">require<\/span> <span class=\"hljs-keyword\">__DIR__<\/span>.<span class=\"hljs-string\">'\/..\/laravel-app\/vendor\/autoload.php'<\/span>;\n$app = <span class=\"hljs-keyword\">require_once<\/span> <span class=\"hljs-keyword\">__DIR__<\/span>.<span class=\"hljs-string\">'\/..\/laravel-app\/bootstrap\/app.php'<\/span>;<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>By default, <code>index.php<\/code> looks for <code>..\/vendor\/autoload.php<\/code>. Since we moved files into <code>laravel-app\/<\/code>, update the paths accordingly. Without this, Laravel won\u2019t boot in production.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>4 \u2014 Configure .htaccess for Routing<\/strong><\/h2>\n\n\n\n<p>Laravel routes everything through <code>public\/index.php<\/code>. Update the <code>.htaccess<\/code> in <code>public_html\/<\/code> to handle this properly:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Apache\" data-shcb-language-slug=\"apache\"><span><code class=\"hljs language-apache\"><span class=\"hljs-section\">&lt;IfModule mod_rewrite.c&gt;<\/span>\n    <span class=\"hljs-section\">&lt;IfModule mod_negotiation.c&gt;<\/span>\n        <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">Options<\/span><\/span> -MultiViews -Indexes\n    <span class=\"hljs-section\">&lt;\/IfModule&gt;<\/span>\n\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteEngine<\/span><\/span> <span class=\"hljs-literal\">On<\/span>\n\n    <span class=\"hljs-comment\"># Redirect Trailing Slashes...<\/span>\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteCond<\/span><\/span> <span class=\"hljs-variable\">%{REQUEST_FILENAME}<\/span> !-d\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteRule<\/span><\/span> ^(.*)\/$ \/<span class=\"hljs-number\">$1<\/span><span class=\"hljs-meta\"> &#91;L,R=301]<\/span>\n\n    <span class=\"hljs-comment\"># Handle Front Controller...<\/span>\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteCond<\/span><\/span> <span class=\"hljs-variable\">%{REQUEST_FILENAME}<\/span> !-d\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteCond<\/span><\/span> <span class=\"hljs-variable\">%{REQUEST_FILENAME}<\/span> !-f\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteRule<\/span><\/span> ^ index.php<span class=\"hljs-meta\"> &#91;L]<\/span>\n<span class=\"hljs-section\">&lt;\/IfModule&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Apache<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">apache<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This ensures that all requests are funneled through Laravel\u2019s front controller, while still serving static assets directly. For a similar setup on Nginx instead of cPanel\/Apache, check <a href=\"\/blog\/laravel-nginx-best-practices-for-production\">Laravel &amp; Nginx: Best Practices for Production<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>5 \u2014 Configure Cron for Scheduler<\/strong><\/h2>\n\n\n\n<p>Laravel\u2019s task scheduler requires a cron job. You can set this in the cPanel &gt; Cron Jobs section:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"Bash\" data-shcb-language-slug=\"bash\"><span><code class=\"hljs language-bash\">* * * * * php \/home\/username\/laravel-app\/artisan schedule:run &gt;&gt; \/dev\/null 2&gt;&amp;1<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Bash<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">bash<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>This runs the Laravel scheduler every minute, which then executes scheduled tasks as defined in <code>app\/Console\/Kernel.php<\/code>. For a production-grade queue and scheduling setup, see <a href=\"\/blog\/how-to-use-laravel-queues-for-faster-performance\">How to Use Laravel Queues for Faster Performance<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>6 \u2014 Secure Your Application<\/strong><\/h2>\n\n\n\n<p>cPanel hosting often comes with Apache and free SSL (via AutoSSL or Let\u2019s Encrypt). Make sure you force HTTPS and add security headers in your <code>.htaccess<\/code> file.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Apache\" data-shcb-language-slug=\"apache\"><span><code class=\"hljs language-apache\"><span class=\"hljs-comment\"># Force HTTPS<\/span>\n<span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteEngine<\/span><\/span> <span class=\"hljs-literal\">On<\/span>\n<span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteCond<\/span><\/span> <span class=\"hljs-variable\">%{HTTPS}<\/span> !=<span class=\"hljs-literal\">on<\/span>\n<span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">RewriteRule<\/span><\/span> ^ https:\/\/<span class=\"hljs-variable\">%{HTTP_HOST}<\/span><span class=\"hljs-variable\">%{REQUEST_URI}<\/span><span class=\"hljs-meta\"> &#91;L,R=301]<\/span>\n\n<span class=\"hljs-comment\"># Security headers<\/span>\n<span class=\"hljs-section\">&lt;IfModule mod_headers.c&gt;<\/span>\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">Header<\/span><\/span> set X-Frame-Options <span class=\"hljs-string\">\"SAMEORIGIN\"<\/span>\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">Header<\/span><\/span> set X-Content-Type-Options <span class=\"hljs-string\">\"nosniff\"<\/span>\n    <span class=\"hljs-attribute\"><span class=\"hljs-nomarkup\">Header<\/span><\/span> set Referrer-Policy <span class=\"hljs-string\">\"strict-origin-when-cross-origin\"<\/span>\n<span class=\"hljs-section\">&lt;\/IfModule&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Apache<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">apache<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>These rules ensure all traffic is encrypted and common browser security headers are applied. For more on security, check <a href=\"\/blog\/how-to-prevent-csrf-xss-and-sql-injection-in-laravel-apps\">How to Prevent CSRF, XSS, and SQL Injection in Laravel Apps<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>7 \u2014 Final Pre-Launch Checks<\/strong><\/h2>\n\n\n\n<p>Before going live, walk through this checklist:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u2705 <code>APP_ENV=production<\/code> and <code>APP_DEBUG=false<\/code><\/li>\n<li>\u2705 Run <code>php artisan config:cache<\/code>, <code>route:cache<\/code>, <code>view:cache<\/code><\/li>\n<li>\u2705 Ensure storage &amp; bootstrap\/cache are writable<\/li>\n<li>\u2705 Public files are inside <code>public_html\/<\/code><\/li>\n<li>\u2705 <code>.env<\/code> is in <code>\/laravel-app\/<\/code> (not exposed)<\/li>\n<li>\u2705 Database migrations and seeders run with <code>--force<\/code><\/li>\n<li>\u2705 Cron job for scheduler is configured<\/li>\n<li>\u2705 HTTPS and security headers are enforced<\/li>\n<\/ul>\n\n\n\n<p>Once complete, your Laravel app is safely deployed to your cPanel hosting environment.<\/p>\n\n\n\n<div class=\"wp-block-spacer\" style=\"height:100px\" aria-hidden=\"true\"><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What\u2019s Next<\/h2>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"\/blog\/laravel-deployment-checklist-for-2025\">Laravel Deployment Checklist for 2025<\/a> \u2014 follow a complete step-by-step checklist before going live.<\/li>\n<li><a href=\"\/blog\/laravel-nginx-best-practices-for-production\">Laravel &amp; Nginx: Best Practices for Production<\/a> \u2014 see how to configure Nginx for high performance and security.<\/li>\n<li><a href=\"\/blog\/automating-laravel-deployments-with-deployer\">Automating Laravel Deployments with Deployer<\/a> \u2014 learn how to set up zero-downtime deployments.<\/li>\n<\/ul>\n\n","protected":false},"excerpt":{"rendered":"<p>How to Deploy Laravel 12 on cPanel Hosting Not every project requires a VPS or cloud infrastructure. Many developers still rely on cPanel hosting for simplicity and cost-effectiveness. Deploying a Laravel 12 application on cPanel comes with its own challenges: shared servers, no SSH access in some cases, and the need to configure the public\/ [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":480,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[74,71,81],"class_list":["post-476","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-laravel","tag-deployment","tag-devops","tag-shared-hosting"],"_links":{"self":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/476","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/comments?post=476"}],"version-history":[{"count":1,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/476\/revisions"}],"predecessor-version":[{"id":479,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/posts\/476\/revisions\/479"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media\/480"}],"wp:attachment":[{"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/media?parent=476"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/categories?post=476"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/1v0.net\/blog\/wp-json\/wp\/v2\/tags?post=476"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}