[{"data":1,"prerenderedAt":737},["ShallowReactive",2],{"navigation_docs":3,"section-navigation-docs":130,"-docs-guides-laravel":164,"-docs-guides-laravel-surround":645,"doc-previews":650},[4,8,50,54,58,62,66,70,74,78,82,86,90,94,98,102,106,110,114,118,122,126],{"title":5,"path":6,"stem":7},"Quickstart","\u002Fdocs\u002Fquickstart","docs\u002F01.quickstart",{"title":9,"path":10,"stem":11,"children":12},"Guides","\u002Fdocs\u002Fguides","docs\u002F02.guides\u002Findex",[13,14,18,22,26,30,34,38,42,46],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},"Next.js","\u002Fdocs\u002Fguides\u002Fnextjs","docs\u002F02.guides\u002F1.nextjs",{"title":19,"path":20,"stem":21},"Nuxt","\u002Fdocs\u002Fguides\u002Fnuxt","docs\u002F02.guides\u002F2.nuxt",{"title":23,"path":24,"stem":25},"SvelteKit","\u002Fdocs\u002Fguides\u002Fsveltekit","docs\u002F02.guides\u002F3.sveltekit",{"title":27,"path":28,"stem":29},"Astro","\u002Fdocs\u002Fguides\u002Fastro","docs\u002F02.guides\u002F4.astro",{"title":31,"path":32,"stem":33},"Express","\u002Fdocs\u002Fguides\u002Fexpress","docs\u002F02.guides\u002F5.express",{"title":35,"path":36,"stem":37},"FastAPI","\u002Fdocs\u002Fguides\u002Ffastapi","docs\u002F02.guides\u002F6.fastapi",{"title":39,"path":40,"stem":41},"Django","\u002Fdocs\u002Fguides\u002Fdjango","docs\u002F02.guides\u002F7.django",{"title":43,"path":44,"stem":45},"Laravel","\u002Fdocs\u002Fguides\u002Flaravel","docs\u002F02.guides\u002F8.laravel",{"title":47,"path":48,"stem":49},"Go","\u002Fdocs\u002Fguides\u002Fgo","docs\u002F02.guides\u002F9.go",{"title":51,"path":52,"stem":53},"Services","\u002Fdocs\u002Fservices","docs\u002F03.services",{"title":55,"path":56,"stem":57},"Deployments","\u002Fdocs\u002Fdeployments","docs\u002F04.deployments",{"title":59,"path":60,"stem":61},"Builds","\u002Fdocs\u002Fbuilds","docs\u002F05.builds",{"title":63,"path":64,"stem":65},"Variables","\u002Fdocs\u002Fvariables","docs\u002F06.variables",{"title":67,"path":68,"stem":69},"Domains","\u002Fdocs\u002Fdomains","docs\u002F07.domains",{"title":71,"path":72,"stem":73},"PostgreSQL","\u002Fdocs\u002Fpostgres","docs\u002F08.postgres",{"title":75,"path":76,"stem":77},"Object storage","\u002Fdocs\u002Fobject-storage","docs\u002F09.object-storage",{"title":79,"path":80,"stem":81},"Volumes","\u002Fdocs\u002Fvolumes","docs\u002F10.volumes",{"title":83,"path":84,"stem":85},"Key-value store","\u002Fdocs\u002Fredis","docs\u002F11.redis",{"title":87,"path":88,"stem":89},"Workspaces","\u002Fdocs\u002Fworkspaces","docs\u002F12.workspaces",{"title":91,"path":92,"stem":93},"Projects","\u002Fdocs\u002Fprojects","docs\u002F13.projects",{"title":95,"path":96,"stem":97},"Environments","\u002Fdocs\u002Fenvironments","docs\u002F14.environments",{"title":99,"path":100,"stem":101},"Eject","\u002Fdocs\u002Feject","docs\u002F15.eject",{"title":103,"path":104,"stem":105},"API","\u002Fdocs\u002Fapi","docs\u002F16.api",{"title":107,"path":108,"stem":109},"CLI","\u002Fdocs\u002Fcli","docs\u002F17.cli",{"title":111,"path":112,"stem":113},"Claude Plugin & MCP","\u002Fdocs\u002Fclaude-plugin","docs\u002F18.claude-plugin",{"title":115,"path":116,"stem":117},"Metrics","\u002Fdocs\u002Fmetrics","docs\u002F19.metrics",{"title":119,"path":120,"stem":121},"Logs","\u002Fdocs\u002Flogs","docs\u002F20.logs",{"title":123,"path":124,"stem":125},"Billing","\u002Fdocs\u002Fbilling","docs\u002F21.billing",{"title":127,"path":128,"stem":129},"Self-hosting","\u002Fdocs\u002Fself-hosting","docs\u002F22.self-hosting",[131,132,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163],{"title":5,"path":6,"stem":7},{"title":9,"path":10,"stem":11,"children":133},[134,135,136,137,138,139,140,141,142,143],{"title":9,"path":10,"stem":11},{"title":15,"path":16,"stem":17},{"title":19,"path":20,"stem":21},{"title":23,"path":24,"stem":25},{"title":27,"path":28,"stem":29},{"title":31,"path":32,"stem":33},{"title":35,"path":36,"stem":37},{"title":39,"path":40,"stem":41},{"title":43,"path":44,"stem":45},{"title":47,"path":48,"stem":49},{"title":51,"path":52,"stem":53},{"title":55,"path":56,"stem":57},{"title":59,"path":60,"stem":61},{"title":63,"path":64,"stem":65},{"title":67,"path":68,"stem":69},{"title":71,"path":72,"stem":73},{"title":75,"path":76,"stem":77},{"title":79,"path":80,"stem":81},{"title":83,"path":84,"stem":85},{"title":87,"path":88,"stem":89},{"title":91,"path":92,"stem":93},{"title":95,"path":96,"stem":97},{"title":99,"path":100,"stem":101},{"title":103,"path":104,"stem":105},{"title":107,"path":108,"stem":109},{"title":111,"path":112,"stem":113},{"title":115,"path":116,"stem":117},{"title":119,"path":120,"stem":121},{"title":123,"path":124,"stem":125},{"title":127,"path":128,"stem":129},{"id":165,"title":166,"body":167,"description":638,"extension":639,"links":640,"meta":641,"navigation":642,"path":44,"seo":643,"stem":45,"__hash__":644},"docs\u002Fdocs\u002F02.guides\u002F8.laravel.md","Deploy a Laravel application",{"type":168,"value":169,"toc":629},"minimark",[170,174,179,208,220,224,235,282,288,292,295,347,366,372,379,383,488,493,503,522,526,540,548,558,562,569,589,596,603,607,625],[171,172,173],"p",{},"A Laravel deployment does more work on your behalf than most. Composer and npm both run, the framework caches get warmed, migrations run, and a web server is configured and started. This guide walks through that lifecycle so you know which parts are yours to control.",[175,176,178],"h2",{"id":177},"start-from-a-fresh-app","Start from a fresh app",[180,181,186],"pre",{"className":182,"code":183,"language":184,"meta":185,"style":185},"language-bash shiki shiki-themes gruvbox-dark-medium gruvbox-dark-medium gruvbox-dark-medium","composer create-project laravel\u002Flaravel my-app\n","bash","",[187,188,189],"code",{"__ignoreMap":185},[190,191,194,198,202,205],"span",{"class":192,"line":193},"line",1,[190,195,197],{"class":196},"sX5TD","composer",[190,199,201],{"class":200},"sQLXx"," create-project",[190,203,204],{"class":200}," laravel\u002Flaravel",[190,206,207],{"class":200}," my-app\n",[171,209,210,211,215,216,219],{},"Push it to GitHub and connect it as in the ",[212,213,214],"a",{"href":6},"quickstart",". A stock Laravel app needs no changes to build, though it will not boot until it has an ",[187,217,218],{},"APP_KEY",", which is the first variable below.",[175,221,223],{"id":222},"during-the-build","During the build",[171,225,226,227,230,231,234],{},"The ",[212,228,229],{"href":60},"build"," recognizes the project from ",[187,232,233],{},"composer.json"," and runs, in order:",[236,237,238,245,252,266],"ol",{},[239,240,241,244],"li",{},[187,242,243],{},"composer install --optimize-autoloader",", with the Composer cache reused between builds.",[239,246,247,248,251],{},"Your frontend build, if there is a ",[187,249,250],{},"package.json",". Laravel's default Vite setup is picked up without configuration.",[239,253,254,257,258,261,262,265],{},[187,255,256],{},"mkdir"," for the ",[187,259,260],{},"storage\u002F"," and ",[187,263,264],{},"bootstrap\u002Fcache"," directories, so a clean checkout has somewhere to write.",[239,267,268,271,272,271,275,261,278,281],{},[187,269,270],{},"php artisan config:cache",", ",[187,273,274],{},"event:cache",[187,276,277],{},"route:cache",[187,279,280],{},"view:cache",".",[171,283,284,285,287],{},"Anything requiring PHP extensions beyond the defaults belongs in ",[187,286,233],{},", where the builder reads them.",[175,289,291],{"id":290},"when-the-container-starts","When the container starts",[171,293,294],{},"The image starts a script rather than a bare server, and that script does three things before serving traffic:",[180,296,298],{"className":182,"code":297,"language":184,"meta":185,"style":185},"php artisan migrate --force\nphp artisan storage:link\nphp artisan optimize:clear && php artisan optimize\n",[187,299,300,315,325],{"__ignoreMap":185},[190,301,302,305,308,311],{"class":192,"line":193},[190,303,304],{"class":196},"php",[190,306,307],{"class":200}," artisan",[190,309,310],{"class":200}," migrate",[190,312,314],{"class":313},"s1Tsi"," --force\n",[190,316,318,320,322],{"class":192,"line":317},2,[190,319,304],{"class":196},[190,321,307],{"class":200},[190,323,324],{"class":200}," storage:link\n",[190,326,328,330,332,335,339,342,344],{"class":192,"line":327},3,[190,329,304],{"class":196},[190,331,307],{"class":200},[190,333,334],{"class":200}," optimize:clear",[190,336,338],{"class":337},"si-ur"," &&",[190,340,341],{"class":196}," php",[190,343,307],{"class":200},[190,345,346],{"class":200}," optimize\n",[171,348,349,353,354,357,358,361,362,365],{},[350,351,352],"strong",{},"Migrations run on every start",", not just on deploy. Repeat runs are harmless, but a failing migration keeps the container from serving. Set ",[187,355,356],{},"RAILPACK_SKIP_MIGRATIONS"," to ",[187,359,360],{},"true"," as a ",[212,363,364],{"href":64},"variable"," if you would rather run them yourself.",[171,367,368,371],{},[350,369,370],{},"The caches are rebuilt at boot",", which is the detail that saves you. Config was cached during the build, when your runtime variables were not necessarily final. Because the start script clears and re-optimizes, the values that end up in the running app are the ones set on the service.",[171,373,374,375,378],{},"Then FrankenPHP serves the application on the port Lucity provides. There is no nginx config, no php-fpm pool and no ",[187,376,377],{},"Procfile"," to write.",[175,380,382],{"id":381},"the-variables-it-needs","The variables it needs",[384,385,386,399],"table",{},[387,388,389],"thead",{},[390,391,392,396],"tr",{},[393,394,395],"th",{},"Variable",[393,397,398],{},"Value",[400,401,402,419,432,451,463],"tbody",{},[390,403,404,409],{},[405,406,407],"td",{},[187,408,218],{},[405,410,411,414,415,418],{},[187,412,413],{},"base64:..."," from ",[187,416,417],{},"php artisan key:generate --show",". Set it once and keep it.",[390,420,421,426],{},[405,422,423],{},[187,424,425],{},"APP_URL",[405,427,428,429,281],{},"Your generated or custom ",[212,430,431],{"href":68},"domain",[390,433,434,443],{},[405,435,436,439,440],{},[187,437,438],{},"APP_ENV"," \u002F ",[187,441,442],{},"APP_DEBUG",[405,444,445,261,448,281],{},[187,446,447],{},"production",[187,449,450],{},"false",[390,452,453,458],{},[405,454,455],{},[187,456,457],{},"DB_CONNECTION",[405,459,460],{},[187,461,462],{},"pgsql",[390,464,465,482],{},[405,466,467,271,470,271,473,271,476,271,479],{},[187,468,469],{},"DB_HOST",[187,471,472],{},"DB_PORT",[187,474,475],{},"DB_DATABASE",[187,477,478],{},"DB_USERNAME",[187,480,481],{},"DB_PASSWORD",[405,483,484,485,281],{},"Linked to the matching values on your ",[212,486,487],{"href":72},"database",[171,489,490,492],{},[187,491,218],{}," deserves two warnings. It encrypts sessions and anything you have encrypted at rest, so generating a fresh one on each deploy logs everyone out and makes old ciphertext unreadable. Generate it once, store it as a variable, leave it alone.",[171,494,495,496,498,499,502],{},"The second warning is about how its absence looks. On this stack a missing ",[187,497,218],{}," does not produce Laravel's familiar key screen. The request returns a 500 and the log shows ",[187,500,501],{},"Cannot modify header information: headers already sent"," from Symfony's response handling, because the exception page fails while rendering itself. If you see that error on a fresh deployment, check the variable before you go looking for a header bug.",[171,504,505,506,271,509,271,512,271,515,271,518,521],{},"The database values map one to one onto the values a Lucity database exposes: ",[187,507,508],{},"host",[187,510,511],{},"port",[187,513,514],{},"dbname",[187,516,517],{},"user",[187,519,520],{},"password",". Link each rather than pasting, and credential rotation stops being an incident.",[175,523,525],{"id":524},"files-go-in-a-bucket-not-on-disk","Files go in a bucket, not on disk",[171,527,528,531,532,535,536,539],{},[187,529,530],{},"storage:link"," runs at boot, which makes ",[187,533,534],{},"public\u002Fstorage"," work, but that disk is part of the container and disappears with it. Uploads that need to survive a deploy belong in a ",[212,537,538],{"href":76},"bucket",":",[180,541,546],{"className":542,"code":544,"language":545},[543],"language-text","FILESYSTEM_DISK=s3\nAWS_ACCESS_KEY_ID     -> accessKeyId\nAWS_SECRET_ACCESS_KEY -> secretAccessKey\nAWS_BUCKET            -> bucket\nAWS_ENDPOINT          -> endpoint\nAWS_DEFAULT_REGION    -> region\nAWS_USE_PATH_STYLE_ENDPOINT=true\n","text",[187,547,544],{"__ignoreMap":185},[171,549,550,551,261,554,557],{},"Install ",[187,552,553],{},"league\u002Fflysystem-aws-s3-v3",[187,555,556],{},"Storage::disk('s3')"," behaves as usual.",[175,559,561],{"id":560},"queues-get-their-own-service","Queues get their own service",[171,563,564,565,568],{},"A queue worker is a long-running process with a different command, so it is a second ",[212,566,567],{"href":52},"service"," in the same project, pointed at the same repository, with its start command set to:",[180,570,572],{"className":182,"code":571,"language":184,"meta":185,"style":185},"php artisan queue:work --tries=3 --max-time=3600\n",[187,573,574],{"__ignoreMap":185},[190,575,576,578,580,583,586],{"class":192,"line":193},[190,577,304],{"class":196},[190,579,307],{"class":200},[190,581,582],{"class":200}," queue:work",[190,584,585],{"class":313}," --tries=3",[190,587,588],{"class":313}," --max-time=3600\n",[171,590,591,592,595],{},"Give it the same variables as the web service so it reaches the same database and the same ",[212,593,594],{"href":84},"key-value store",", and leave its port unset: it serves no traffic and needs no domain. Scale it by raising replicas on that service alone.",[171,597,598,599,602],{},"The scheduler works the same way, with ",[187,600,601],{},"php artisan schedule:work"," as its command.",[175,604,606],{"id":605},"next-steps","Next steps",[608,609,610,615,620],"ul",{},[239,611,612,614],{},[212,613,83],{"href":84}," for queues, cache and sessions",[239,616,617,619],{},[212,618,75],{"href":76}," for uploads",[239,621,622,624],{},[212,623,55],{"href":56}," for rollout behavior and rollbacks",[626,627,628],"style",{},"html pre.shiki code .sX5TD, html code.shiki .sX5TD{--shiki-light:#FABD2F;--shiki-default:#FABD2F;--shiki-dark:#FABD2F}html pre.shiki code .sQLXx, html code.shiki .sQLXx{--shiki-light:#B8BB26;--shiki-default:#B8BB26;--shiki-dark:#B8BB26}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s1Tsi, html code.shiki .s1Tsi{--shiki-light:#D3869B;--shiki-default:#D3869B;--shiki-dark:#D3869B}html pre.shiki code .si-ur, html code.shiki .si-ur{--shiki-light:#A89984;--shiki-default:#A89984;--shiki-dark:#A89984}",{"title":185,"searchDepth":317,"depth":317,"links":630},[631,632,633,634,635,636,637],{"id":177,"depth":317,"text":178},{"id":222,"depth":317,"text":223},{"id":290,"depth":317,"text":291},{"id":381,"depth":317,"text":382},{"id":524,"depth":317,"text":525},{"id":560,"depth":317,"text":561},{"id":605,"depth":317,"text":606},"Deploy a Laravel application on Lucity, with migrations, caches and a queue worker, and no server to configure.","md",null,{},{"title":43},{"title":166,"description":638},"VK-73lzmpjcazkQ-H-DjvKq-uKBm9QfPzkvn10uO7eI",[646,648],{"title":39,"path":40,"stem":41,"description":647,"children":-1},"Deploy a Django project on Lucity, with migrations that run themselves and static files that do not.",{"title":47,"path":48,"stem":49,"description":649,"children":-1},"Deploy a Go service on Lucity. Compiled in the build, shipped as a binary, nothing else in the image.",[651,654,656,659,662,665,668,671,674,676,677,679,682,684,686,688,690,692,694,696,698,700,702,704,706,708,710,712,714,716,718,720,722,725,729,733],{"path":6,"title":652,"description":653},"Deploy your first service","Deploy an app to Lucity, put it on a public domain, and connect a PostgreSQL database and an object storage bucket in about fifteen minutes.",{"path":655,"title":9,"description":640},"\u002Fdocs\u002Fguides\u002F.navigation",{"path":16,"title":657,"description":658},"Deploy a Next.js app","Deploy a Next.js app on Lucity, with a database, environment variables that behave, and no Dockerfile.",{"path":20,"title":660,"description":661},"Deploy a Nuxt app","Deploy a Nuxt app on Lucity. Nitro output, runtime config, and a database, with no preset to pick.",{"path":24,"title":663,"description":664},"Deploy a SvelteKit app","Deploy a SvelteKit app on Lucity. One adapter change stands between a fresh project and a running service.",{"path":28,"title":666,"description":667},"Deploy an Astro site","Deploy an Astro site on Lucity, static by default and server rendered when you add an adapter.",{"path":32,"title":669,"description":670},"Deploy an Express API","Deploy an Express API on Lucity. Three requirements, none of them platform-specific.",{"path":36,"title":672,"description":673},"Deploy a FastAPI service","Deploy a FastAPI service on Lucity. Detection is picky about layout, and the fix is one setting.",{"path":40,"title":675,"description":647},"Deploy a Django project",{"path":44,"title":166,"description":638},{"path":48,"title":678,"description":649},"Deploy a Go service",{"path":10,"title":680,"description":681},"Deploy your framework","Deploy guides for the frameworks people actually ship: Next.js, Nuxt, SvelteKit, Astro, Express, FastAPI, Django, Laravel, and Go.",{"path":52,"title":51,"description":683},"Services are the deployable units of a project: what they are, how they are configured, and how they scale.",{"path":56,"title":55,"description":685},"How a deployment goes live on Lucity, and the ways to trigger one.",{"path":60,"title":59,"description":687},"How Lucity turns your source code into a container image.",{"path":64,"title":63,"description":689},"Configuration for your services: service variables, shared variables, and dynamic variables.",{"path":68,"title":67,"description":691},"Put a service on the internet. Use a platform hostname for quick tests, or a domain you own.",{"path":72,"title":71,"description":693},"Managed PostgreSQL databases, replicated and backed up, connected to your services without copying credentials.",{"path":76,"title":75,"description":695},"S3-compatible buckets for uploads, exports and anything else your service needs to keep.",{"path":80,"title":79,"description":697},"Persistent disks for services that need to keep state on the filesystem.",{"path":84,"title":83,"description":699},"A Redis®-compatible key-value store for caching, sessions and queues.",{"path":88,"title":87,"description":701},"Workspaces represent your organization in Lucity, with their own members, isolation and billing.",{"path":92,"title":91,"description":703},"Projects group services, databases and the environments they run in.",{"path":96,"title":95,"description":705},"Development, staging, production: isolated copies of the same application.",{"path":100,"title":99,"description":707},"Download a project as a Helm chart and run it on a Kubernetes cluster of your own.",{"path":104,"title":103,"description":709},"The GraphQL API behind the dashboard, with an interactive playground.",{"path":108,"title":107,"description":711},"Deploy and manage your services from a terminal or a CI pipeline.",{"path":112,"title":111,"description":713},"Deploy and manage your services from Claude Code, Codex, Cursor or any other MCP client.",{"path":116,"title":115,"description":715},"CPU and memory for every service, and disk usage for every volume.",{"path":120,"title":119,"description":717},"What your services print while they run, and the output of every deployment step.",{"path":124,"title":123,"description":719},"Plans, resource usage, the free trial, and what happens when a payment fails.",{"path":128,"title":127,"description":721},"Run the whole platform on a Kubernetes cluster you own, using the same two Helm charts we run ourselves.",{"path":723,"title":724,"description":640},"\u002Flegal\u002F.navigation","Legal",{"path":726,"title":727,"description":728},"\u002Flegal\u002Fdata-processing-agreement","Data Processing Agreement","How Lucity processes personal data on your behalf.",{"path":730,"title":731,"description":732},"\u002Flegal\u002Fprivacy-policy","Privacy Policy","How Lucity handles your data.",{"path":734,"title":735,"description":736},"\u002Flegal\u002Fterms-of-use","Terms of Use","Terms governing your use of Lucity.",1791216729422]