{"id":842,"date":"2025-01-17T18:16:31","date_gmt":"2025-01-17T18:16:31","guid":{"rendered":"https:\/\/bendauphinee.com\/writing\/?p=842"},"modified":"2025-01-22T22:54:24","modified_gmt":"2025-01-22T22:54:24","slug":"an-app-from-scratch-part-9-setting-up-our-production-server-and-deployment-us1-c4","status":"publish","type":"post","link":"https:\/\/bendauphinee.com\/writing\/2025\/01\/17\/an-app-from-scratch-part-9-setting-up-our-production-server-and-deployment-us1-c4\/","title":{"rendered":"An App From Scratch: Part 9 \u2013\u00a0Setting Up Our Production Server And Deployment (US1-C4)"},"content":{"rendered":"\n<p class=\"has-small-font-size\">9 minute reading time; ~1720 words<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity is-style-wide\"\/>\n\n\n\n<p>Welcome and hello!<\/p>\n\n\n\n<p>This post is going to take the work we&#8217;ve done so far, and put it where it can be used. We&#8217;re going to walk through designing an automated deployment process, and some cleanup that we have to do around the branding as part of taking it to production.<\/p>\n\n\n\n<p>Let&#8217;s dig into it, and put our work in front of the world!<\/p>\n\n\n\n<p class=\"has-accent-5-background-color has-background\">If you haven&#8217;t read the previous posts, I&#8217;d suggest you start at <a href=\"https:\/\/bendauphinee.com\/writing\/2024\/12\/20\/designing-an-app-from-scratch-part-1-what-to-build\/\" data-type=\"link\" data-id=\"https:\/\/bendauphinee.com\/writing\/2024\/12\/20\/designing-an-app-from-scratch-part-1-what-to-build\/\">An App From Scratch: Part 1 \u2013 What To Build<\/a>. You can also find all the related documents and code here: <a href=\"https:\/\/bendauphinee.com\/writing\/building-tailgunner\/\">Building Tailgunner<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">What Do I See?<\/h2>\n\n\n\n<p>Let&#8217;s take a look at the final card in this feature.<\/p>\n\n\n\n<div class=\"wp-block-group has-base-color has-contrast-background-color has-text-color has-background has-link-color wp-elements-71f44af614ec582d1fd30b1e261db233 has-global-padding is-layout-constrained wp-container-core-group-is-layout-9597dc02 wp-block-group-is-layout-constrained\" style=\"padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--10);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--10)\">\n<p class=\"has-contrast-color has-accent-3-background-color has-text-color has-background has-link-color wp-elements-b0a9e98e2beebf2c46a31bc2d1dee722\" style=\"padding-top:0;padding-right:0.3rem;padding-bottom:0;padding-left:0.3rem\"><strong>Card<\/strong>: US1-C4<\/p>\n\n\n\n<div class=\"wp-block-columns is-layout-flex wp-container-core-columns-is-layout-28f84493 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h4 class=\"wp-block-heading has-base-color has-text-color has-background has-link-color wp-elements-4bf8fa03559180f6a65d7015bc498d5b\" style=\"background-color:#dddddd;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--10);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--10)\">Title<\/h4>\n\n\n\n<p>Set up production server and deployment<\/p>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<h4 class=\"wp-block-heading has-base-color has-text-color has-background has-link-color wp-elements-208c9d0f6b2264867b69c2622d7d9968\" style=\"background-color:#dddddd;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--10);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--10)\">Type<\/h4>\n\n\n\n<p>Task<\/p>\n<\/div>\n<\/div>\n\n\n\n<h4 class=\"wp-block-heading has-base-color has-text-color has-background has-link-color wp-elements-c2d2f57ca0c39c3684d432537b97ceee\" style=\"background-color:#dddddd;padding-top:var(--wp--preset--spacing--10);padding-right:var(--wp--preset--spacing--10);padding-bottom:var(--wp--preset--spacing--10);padding-left:var(--wp--preset--spacing--10)\">Description<\/h4>\n\n\n\n<p class=\"has-medium-font-size\">Create a production web server, and implement a deployment workflow to get our code into production.<\/p>\n\n\n\n<p><strong>Acceptance Criteria<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A server exists for <code>tailgunner.app<\/code>, running the latest main branch code.<\/li>\n\n\n\n<li>New merges to main are deployed to the production server.<\/li>\n<\/ul>\n<\/div>\n\n\n\n<h3 class=\"wp-block-heading\">What I Need To Do<\/h3>\n\n\n\n<p>Reviewing the system diagram and acceptance criteria, we can break down these tasks:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Set up server environment<\/li>\n\n\n\n<li>Add credentials to GitHub<\/li>\n\n\n\n<li>Create a GitHub Action build \/ push pipeline<\/li>\n\n\n\n<li>Port the current homepage into Laravel and update branding<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Putting It Into Action<\/h2>\n\n\n\n<h4 class=\"wp-block-heading\">Set up server environment<\/h4>\n\n\n\n<p>First of all, I want to lay out the deployment structure on the server.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" data-code=\"|-- base directory\n|   \u2514\u2500\u2500 deployments                            &lt;- Where we upload the deployment files\n|       \u2514\u2500\u2500 deploy-2025-01-16-14-48-32.tar.gz  &lt;- A deployment file\n|       \u2514\u2500\u2500 releases                           &lt;- Where each release gets unpacked to\n|           \u2514\u2500\u2500 2025-01-16-14-48-32            &lt;- An unpacked release\n\n|       \u2514\u2500\u2500 workflows                          &lt;- Where the workflow script gets stored\n|           \u2514\u2500\u2500 deploy-to-prod.sh              &lt;- The workflow script\n    \n    # public_html gets symlinked (shortcut) to the current release folder's code\n|   \u2514\u2500\u2500 public_html -&gt; \/home\/&lt;username&gt;\/deployments\/releases\/2025-01-16-14-48-32\/src\n\n|   \u2514\u2500\u2500 shared          &lt;- Where we will store files that don't change in each release\n|       \u2514\u2500\u2500 .env        &lt;- The production environment settings\n|       \u2514\u2500\u2500 storage     &lt;- Laravel's file storage directory\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #DCDCAA\">--<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">base<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">directory<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|   <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deployments<\/span><span style=\"color: #D4D4D4\">                            &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Where<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">we<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">upload<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">the<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deployment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">files<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|       <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deploy-2025-01-16-14-48-32.tar.gz<\/span><span style=\"color: #D4D4D4\">  &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">A<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deployment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|       <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">releases<\/span><span style=\"color: #D4D4D4\">                           &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Where<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">each<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">release<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">gets<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">unpacked<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">to<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|           <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">2025<\/span><span style=\"color: #CE9178\">-01-16-14-48-32<\/span><span style=\"color: #D4D4D4\">            &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">An<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">unpacked<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">release<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|       <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">workflows<\/span><span style=\"color: #D4D4D4\">                          &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Where<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">the<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">workflow<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">script<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">gets<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">stored<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|           <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deploy-to-prod.sh<\/span><span style=\"color: #D4D4D4\">              &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">The<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">workflow<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">script<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># public_html gets symlinked (shortcut) to the current release folder&#39;s code<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|   <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">public_html<\/span><span style=\"color: #D4D4D4\"> -&gt; <\/span><span style=\"color: #CE9178\">\/home\/<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #CE9178\">usernam<\/span><span style=\"color: #D4D4D4\">e&gt;<\/span><span style=\"color: #CE9178\">\/deployments\/releases\/2025-01-16-14-48-32\/src<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">|   <\/span><span style=\"color: #DCDCAA\">\u2514\u2500\u2500<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">shared<\/span><span style=\"color: #D4D4D4\">          &lt;<\/span><span style=\"color: #CE9178\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Where<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">we<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">will<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">store<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">files<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">that<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">don&#39;t change in each release<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">|       \u2514\u2500\u2500 .env        &lt;- The production environment settings<\/span><\/span>\n<span class=\"line\"><span style=\"color: #CE9178\">|       \u2514\u2500\u2500 storage     &lt;- Laravel&#39;s<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">file<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">storage<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">directory<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>This structure will allow us to make instant switches between releases, and gives us the ability to switch back to a previous release by re-linking the <code>public_html<\/code> directory to the desired one.<\/p>\n\n\n\n<p>Next, since I&#8217;m using cPanel for my hosting, there were a few extra server configuration things to do.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" data-code=\"# Go to the cPanel settings for the user (as root)\n$ cd \/var\/cpanel\/userdata\/&lt;username&gt;\/\n\n# Edit the config for the domain, and change the DocumentRoot\n# (where files are served from), from public_html to public_html\/public\n# because that's how Laravel serves its content.\n$ nano tailgunner.app\ndocumentroot: \/home\/&lt;username&gt;\/public_html\/public\n\n# Make the same change to our https config\n$ nano tailgunner.app_SSL\ndocumentroot: \/home\/&lt;username&gt;\/public_html\/public\n\n# Get cPanel to rebuild our httpd configurations\n$ \/scripts\/rebuildhttpdconf\nBuilt \/etc\/apache2\/conf\/httpd.conf OK\n\n# Restart the webserver so the changes take effect\n$ systemctl restart httpd\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #6A9955\"># Go to the cPanel settings for the user (as root)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">cd<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">\/var\/cpanel\/userdata\/<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #CE9178\">usernam<\/span><span style=\"color: #D4D4D4\">e&gt;<\/span><span style=\"color: #CE9178\">\/<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Edit the config for the domain, and change the DocumentRoot<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># (where files are served from), from public_html to public_html\/public<\/span><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># because that&#39;s how Laravel serves its content.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">nano<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">tailgunner.app<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">documentroot:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">\/home\/<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #CE9178\">usernam<\/span><span style=\"color: #D4D4D4\">e&gt;<\/span><span style=\"color: #CE9178\">\/public_html\/public<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Make the same change to our https config<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">nano<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">tailgunner.app_SSL<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">documentroot:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">\/home\/<\/span><span style=\"color: #D4D4D4\">&lt;<\/span><span style=\"color: #CE9178\">usernam<\/span><span style=\"color: #D4D4D4\">e&gt;<\/span><span style=\"color: #CE9178\">\/public_html\/public<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Get cPanel to rebuild our httpd configurations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">\/scripts\/rebuildhttpdconf<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">Built<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">\/etc\/apache2\/conf\/httpd.conf<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">OK<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #6A9955\"># Restart the webserver so the changes take effect<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">systemctl<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">restart<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">httpd<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The server needs to only be restarted once. After that, we can change the symlink for <code>public_html<\/code> that we created earlier, and should have no issues.<\/p>\n\n\n\n<p>For GitHub, I granted the account <a href=\"https:\/\/support.cpanel.net\/hc\/en-us\/articles\/360051992634-What-are-the-differences-between-Normal-and-Jailed-Shell\">jailed shell access<\/a>, and generated an SSH key set using the <code>ssh-keygen<\/code> command.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" data-code=\"$ ssh-keygen -t ed25519 -f ~\/.ssh\/github_deploy\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">ssh-keygen<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">-t<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">ed25519<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">-f<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">~\/.ssh\/github_deploy<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The other thing we have to do is add our new key into the <code>authorized_keys<\/code> list for the account, so GitHub can use it to access the server.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" data-code=\"$ cat ~\/.ssh\/github_deploy.pub &gt;&gt; ~\/.ssh\/authorized_keys\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">cat<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">~\/.ssh\/github_deploy.pub<\/span><span style=\"color: #D4D4D4\"> &gt;&gt; <\/span><span style=\"color: #CE9178\">~\/.ssh\/authorized_keys<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<h4 class=\"wp-block-heading\">Add credentials to GitHub<\/h4>\n\n\n\n<p>To configure GitHub to be able to access my production server, I need to set up a new <a href=\"https:\/\/docs.github.com\/en\/actions\/managing-workflow-runs-and-deployments\/managing-deployments\/managing-environments-for-deployment\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">Environment<\/a> and add <a href=\"https:\/\/docs.github.com\/en\/actions\/security-for-github-actions\/security-guides\/using-secrets-in-github-actions\" target=\"_blank\" rel=\"noreferrer noopener nofollow\">secrets<\/a> for our deployment script to use.<\/p>\n\n\n\n<p>To do this, we go to the Environment settings for the Tailgunner repo (Settings -&gt; Environments), and created a new environment. After that, we add a few secrets:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>the <code>SERVER_HOST<\/code> to contain the address of the server.<\/li>\n\n\n\n<li>the <code>SERVER_SSH_KEY<\/code> to hold the SSH private key that we just set up.<\/li>\n\n\n\n<li>the <code>SERVER_USER<\/code> has the username we&#8217;ve set up the private key for.<\/li>\n<\/ul>\n\n\n\n<p>To get the contents of the key to put into the <code>SERVER_SSH_KEY<\/code>, we just have to read it from the server and copy the contents into the new secret.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .75rem);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Bash<\/span><span role=\"button\" tabindex=\"0\" data-code=\"$ [tailgunner8vk@fire ~]$ cat ~\/.ssh\/github_deploy\n-----BEGIN OPENSSH PRIVATE KEY-----\n...\n-----END OPENSSH PRIVATE KEY-----\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">$<\/span><span style=\"color: #D4D4D4\"> [tailgunner8vk@fire <\/span><span style=\"color: #CE9178\">~]<\/span><span style=\"color: #D4D4D4\">$ <\/span><span style=\"color: #CE9178\">cat<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">~\/.ssh\/github_deploy<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">-----BEGIN<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">OPENSSH<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">PRIVATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">KEY-----<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">-----END<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">OPENSSH<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">PRIVATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">KEY-----<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>NOTE: GitHub secrets let you input or overwrite their contents but will not display previous values.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"375\" src=\"https:\/\/bendauphinee.com\/writing\/wp-content\/uploads\/2025\/01\/image-16-1024x375.png\" alt=\"\" class=\"wp-image-851\" srcset=\"https:\/\/bendauphinee.com\/writing\/wp-content\/uploads\/2025\/01\/image-16-1024x375.png 1024w, https:\/\/bendauphinee.com\/writing\/wp-content\/uploads\/2025\/01\/image-16-300x110.png 300w, https:\/\/bendauphinee.com\/writing\/wp-content\/uploads\/2025\/01\/image-16-768x281.png 768w, https:\/\/bendauphinee.com\/writing\/wp-content\/uploads\/2025\/01\/image-16.png 1225w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">Create a GitHub Action build \/ push pipeline<\/h4>\n\n\n\n<p>I thought this step would be the easiest, but it took a full day of effort to get right. I&#8217;m going to outline what the main script does here (and highlight some specific pieces you might find useful).<\/p>\n\n\n\n<p>To help guide you, under the Steps section (line 16), you&#8217;ll see the steps the script follows. Each step is named and will appear in the action\u2019s run log as well. I&#8217;ve replaced parts of the script with <code>...<\/code> so we can focus on the most interesting pieces, but you can find <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/blob\/7ed3c43e4044aa67ec0fad262122efa4ddbd2a73\/.github\/workflows\/deploy.yml\" target=\"_blank\" rel=\"noreferrer noopener\">the whole script here<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">.github\/workflows\/deploy.yml<\/span><span role=\"button\" tabindex=\"0\" data-code=\"name: Build and Deploy\n\non:\n    push:\n      branches:\n        - main\n        - '**' # Allow all branches, for testing purposes.\n\n    workflow_dispatch: # Allow manual triggers\n\njobs:\n  deploy:\n    # Define the environment name so we can get the settings from GitHub\n    environment: Tailgunner Production\n\n    steps:\n      - name: Checkout code\n        uses: actions\/checkout@v4\n        with:\n          # Shallow clone for faster checkout\n          fetch-depth: 1\n\n      - name: Setup PHP\n      - name: Install Composer dependencies\n\n      - name: Setup Node.js\n        uses: actions\/setup-node@v4\n        with:\n          ...\n          # Specifies non-default lock file location\n          cache-dependency-path: '.\/src\/package-lock.json'\n\n      - name: Install NPM dependencies &amp; build assets\n      - name: Create deployment package\n\n      - name: Copy deployment package and script\n        uses: appleboy\/scp-action@master\n        with:\n          ...\n          # Copy both the deployment archive and script to the server\n          source: &quot;src\/deploy-*.tar.gz,.github\/workflows\/deploy-to-prod.sh&quot;\n          \n          # Into the deployments directory\n          target: &quot;~\/deployments\/&quot;\n          \n          # Remove the first part of the path\n          # src\/deploy-*.tar.gz                    ~\/deployments\/deploy-*.tar.gz\n          # .github\/workflows\/deploy-to-prod.sh    ~\/deployments\/workflows\/deploy-to-prod.sh\n          strip_components: 1\n\n          # Overwrite existing files so we can put new deploy script versions up\n          overwrite: true\n\n      - name: Unpack and finalize\n        uses: appleboy\/ssh-action@master\n        with:\n          ...\n          script: |\n            # Make the script executable\n            chmod +x ~\/deployments\/workflows\/deploy-to-prod.sh\n            \n            # Run it on the server\n            ~\/deployments\/workflows\/deploy-to-prod.sh\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #DCDCAA\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Build<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">and<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Deploy<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">on:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">push:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">branches:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">main<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;**&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #6A9955\"># Allow all branches, for testing purposes.<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">workflow_dispatch:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #6A9955\"># Allow manual triggers<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #DCDCAA\">jobs<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #DCDCAA\">deploy:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\"># Define the environment name so we can get the settings from GitHub<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">environment:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Tailgunner<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Production<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">steps:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Checkout<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">code<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">uses:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">actions\/checkout@v4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">with:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Shallow clone for faster checkout<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">fetch-depth:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Setup<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">PHP<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Install<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Composer<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">dependencies<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Setup<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Node.js<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">uses:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">actions\/setup-node@v4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">with:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Specifies non-default lock file location<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">cache-dependency-path:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;.\/src\/package-lock.json&#39;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Install<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">NPM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">dependencies<\/span><span style=\"color: #D4D4D4\"> &amp; <\/span><span style=\"color: #DCDCAA\">build<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">assets<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Create<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deployment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">package<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Copy<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">deployment<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">package<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">and<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">script<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">uses:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">appleboy\/scp-action@master<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">with:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Copy both the deployment archive and script to the server<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">source<\/span><span style=\"color: #D4D4D4\">: <\/span><span style=\"color: #CE9178\">&quot;src\/deploy-*.tar.gz,.github\/workflows\/deploy-to-prod.sh&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Into the deployments directory<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">target:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&quot;~\/deployments\/&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Remove the first part of the path<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># src\/deploy-*.tar.gz                    ~\/deployments\/deploy-*.tar.gz<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># .github\/workflows\/deploy-to-prod.sh    ~\/deployments\/workflows\/deploy-to-prod.sh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">strip_components:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #B5CEA8\">1<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #6A9955\"># Overwrite existing files so we can put new deploy script versions up<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">overwrite:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">true<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #DCDCAA\">-<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">name:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">Unpack<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">and<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">finalize<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">uses:<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">appleboy\/ssh-action@master<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #DCDCAA\">with:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">...<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #DCDCAA\">script:<\/span><span style=\"color: #D4D4D4\"> |<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #6A9955\"># Make the script executable<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">chmod<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">+x<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">~\/deployments\/workflows\/deploy-to-prod.sh<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #6A9955\"># Run it on the server<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #DCDCAA\">~\/deployments\/workflows\/deploy-to-prod.sh<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>After a lot of testing (64 commits and 59 workflow runs \ud83d\ude2a), everything works and now I can <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/5\" data-type=\"link\" data-id=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/5\">merge the PR<\/a>, enabling future merges to auto-deploy to the production server!<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Port the current homepage into Laravel and update branding<\/h4>\n\n\n\n<p>Currently, there&#8217;s a static page on the domain that lists the posts in this series. With automated deployments now in place, it&#8217;s time to take that content and replace Laravel&#8217;s default welcome page. Along with this, we&#8217;ll also to update the branding from Laravel to Tailgunner. <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/6\" target=\"_blank\" rel=\"noreferrer noopener\">PR<\/a>, <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/7\" data-type=\"link\" data-id=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/7\" target=\"_blank\" rel=\"noreferrer noopener\">PR<\/a>, <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/8\" target=\"_blank\" rel=\"noreferrer noopener\">PR<\/a>, <a href=\"https:\/\/github.com\/bendauphinee\/tailgunner\/pull\/9\" target=\"_blank\" rel=\"noreferrer noopener\">PR<\/a><\/p>\n\n\n\n<p>The changes we&#8217;ve made are:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Replaced the default main page with our static website content (a list of blog posts)<\/li>\n\n\n\n<li>Replaced all instances of the app logo and favicon with the Tailgunner logo<\/li>\n\n\n\n<li>Created a new CSS file to contain the styles for the main page<\/li>\n\n\n\n<li>Added a display of the PHP and Laravel versions to the main page<\/li>\n\n\n\n<li>Updated the dashboard page to replace the Laravel default content<\/li>\n\n\n\n<li>Fixed the README to account for the new logo location<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>The single biggest challenge in this one was in figuring out how to create the action, and getting it working correctly. There&#8217;s not an easy way to do this part of the process. Every single commit triggers the action to test, which took between 30-45 seconds per run. As you can read from the highlighted lines in my commit log below, it can at times be frustrating.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.75rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .75rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">Commit Log &#8211; Deploy Script<\/span><span role=\"button\" tabindex=\"0\" data-code=\"* 69d3843 US1-C4 First version of prod deploy script\n* 02a46cc US1-C4 Move the scripts to the correct location\n* 8b65df8 US1-C4 Enable for all branches\n* 9006597 US1-C4 Set working directory\n* d5382dc US1-C4 Fix paths\n* 2a7ac12 US1-C4 Try tar a different way\n* 0a5812e US1-C4 Break up the copy and deploy steps\n* 27b8936 US1-C4 Debug this step\n* bbd063d US1-C4 Test just the scp action\n* 45ba536 US1-C4 Debug if the secrets are working\n* 17cdf51 US1-C4 Set the environment to see if that helps\n* ca500c9 US1-C4 Clean up some debugging\n* 4a13e05 US1-C4 Restored the original deployment script\n* 5c7abfd US1-C4 Updated deploy scripts\n* c4e9d4c US1-C4 Removed some deploy steps\n* 93530f4 US1-C4 Changes to where we're putting the upload\n* 4e0b99a US1-C4 Changed the paths for deployment\n* 8d7ef41 US1-C4 Added some deployment setup steps\n* bd90a79 US1-C4 Added some deployment setup steps\n* e21d2ac US1-C4 See of we can fix the file naming issue\n* 85b028f US1-C4 Clean up and fix the release pathing\n* 4bbfcdb US1-C4 Fix some build configs\n* 2d57513 US1-C4 Fix the deploy\n* 13b68d7 US1-C4 We're maybe already in this dir\n* 36daae8 US1-C4 Vite build is being annoying\n* ce8c085 US1-C4 Try again to get Vite to compile\n* ba586ed US1-C4 More changes to see what's wrong with Vite\n* cc4a381 US1-C4 Try again with Vite\n* 94fc3fd US1-C4 Rewrite the npm\n* 956b9c4 US1-C4 Missing dayjs\n* a6c67bb US1-C4 Revert our Vite changes and remove the hot file\n* 7b23c66 US1-C4 See if this build works\n* db25f12 US1-C4 Fix the dependencies\n* 2d48b6a US1-C4 Add some debugging\n* 37b8c5c US1-C4 Change some build pieces\n* 3182b85 US1-C4 Change the deploy script to set up an env\n* a1d9b4d US1-C4 Changes to build script\n* 3fa6314 US1-C4 Re-point web to the new release path\n* 6e8df0a US1-C4 Add some file cleanup\n* f210b4f US1-C4 Bypass production warning\n* b276cdf US1-C4 Move deploy script to new file\n* 6e9f68e US1-C4 The deploy script ended up in the wrong place, also we forgot to add it\n* 478357f US1-C4 Minor optimizations\n* 55301b4 US1-C4 Build script optimizations and re-aligned package-lock.json\n* 5641b29 US1-C4 Revert file handling change\n* d350c8b US1-C4 File handling fix\n* dd0679c US1-C4 Fix the filename\n* a9ddff7 US1-C4 Testing\n* 859fc0d US1-C4 Another test\n* ea96d5f US1-C4 Try again\n* ce173c3 US1-C4 Test\n* 5ab53e4 US1-C4 Another test\n* ad453c2 US1-C4 Test\n* cc80ee9 US1-C4 Maybe this works?\n* f8bac97 US1-C4 Re-organize the build\n* 70eb4d2 US1-C4 Move the Vite vars to GitHub Actions defined environment\n* 01f74b8 US1-C4\n* 8f56b57 US1-C4 Do we need these vars for the app to build properly?\n* 8cdb640 US1-C4 Minor tweaks\n* 6940d47 US1-C4 Clean up some path name handling\n* 1b8f85c US1-C4 Some small changes\n* 27a89cb US1-C4 Message tweaks\n* 86322e4 US1-C4 Don't need this whitespace\n* 1f71469 US1-C4 Remove debugging flag\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">* 69d3843 US1-C4 First version of prod deploy script<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 02a46cc US1-C4 Move the scripts to the correct location<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 8b65df8 US1-C4 Enable for all branches<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 9006597 US1-C4 Set working directory<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* d5382dc US1-C4 Fix paths<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 2a7ac12 US1-C4 Try tar a different way<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 0a5812e US1-C4 Break up the copy and deploy steps<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 27b8936 US1-C4 Debug this step<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* bbd063d US1-C4 Test just the scp action<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 45ba536 US1-C4 Debug if the secrets are working<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 17cdf51 US1-C4 Set the environment to see if that helps<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ca500c9 US1-C4 Clean up some debugging<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 4a13e05 US1-C4 Restored the original deployment script<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 5c7abfd US1-C4 Updated deploy scripts<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* c4e9d4c US1-C4 Removed some deploy steps<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 93530f4 US1-C4 Changes to where we&#39;re putting the upload<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 4e0b99a US1-C4 Changed the paths for deployment<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 8d7ef41 US1-C4 Added some deployment setup steps<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* bd90a79 US1-C4 Added some deployment setup steps<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* e21d2ac US1-C4 See of we can fix the file naming issue<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 85b028f US1-C4 Clean up and fix the release pathing<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 4bbfcdb US1-C4 Fix some build configs<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 2d57513 US1-C4 Fix the deploy<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 13b68d7 US1-C4 We&#39;re maybe already in this dir<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 36daae8 US1-C4 Vite build is being annoying<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ce8c085 US1-C4 Try again to get Vite to compile<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ba586ed US1-C4 More changes to see what&#39;s wrong with Vite<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* cc4a381 US1-C4 Try again with Vite<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 94fc3fd US1-C4 Rewrite the npm<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 956b9c4 US1-C4 Missing dayjs<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* a6c67bb US1-C4 Revert our Vite changes and remove the hot file<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 7b23c66 US1-C4 See if this build works<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* db25f12 US1-C4 Fix the dependencies<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 2d48b6a US1-C4 Add some debugging<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 37b8c5c US1-C4 Change some build pieces<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 3182b85 US1-C4 Change the deploy script to set up an env<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* a1d9b4d US1-C4 Changes to build script<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 3fa6314 US1-C4 Re-point web to the new release path<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 6e8df0a US1-C4 Add some file cleanup<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* f210b4f US1-C4 Bypass production warning<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* b276cdf US1-C4 Move deploy script to new file<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 6e9f68e US1-C4 The deploy script ended up in the wrong place, also we forgot to add it<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 478357f US1-C4 Minor optimizations<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 55301b4 US1-C4 Build script optimizations and re-aligned package-lock.json<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 5641b29 US1-C4 Revert file handling change<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* d350c8b US1-C4 File handling fix<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* dd0679c US1-C4 Fix the filename<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* a9ddff7 US1-C4 Testing<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 859fc0d US1-C4 Another test<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ea96d5f US1-C4 Try again<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ce173c3 US1-C4 Test<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* 5ab53e4 US1-C4 Another test<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* ad453c2 US1-C4 Test<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">* cc80ee9 US1-C4 Maybe this works?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* f8bac97 US1-C4 Re-organize the build<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 70eb4d2 US1-C4 Move the Vite vars to GitHub Actions defined environment<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 01f74b8 US1-C4<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 8f56b57 US1-C4 Do we need these vars for the app to build properly?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 8cdb640 US1-C4 Minor tweaks<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 6940d47 US1-C4 Clean up some path name handling<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 1b8f85c US1-C4 Some small changes<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 27a89cb US1-C4 Message tweaks<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 86322e4 US1-C4 Don&#39;t need this whitespace<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">* 1f71469 US1-C4 Remove debugging flag<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>I originally expected this process to take an hour or two, but when I got into the weeds, it turned out that there were a lot more pieces to get working than I expected.<\/p>\n\n\n\n<p>While it was more involved than I originally expected, it was one of the most interesting parts of this work so far, learning how Actions work, and figuring out how to deploy to a cPanel server.<\/p>\n\n\n\n<p>I hope along the way, you also found something interesting or helpful in my work! Look for the next part soon, <a href=\"https:\/\/bendauphinee.com\/writing\/2025\/01\/22\/an-app-from-scratch-part-10-reflections-and-template-editing\/\" data-type=\"post\" data-id=\"903\">where we&#8217;re going to zoom out a bit and talk about the feature we&#8217;ve delivered, and build the template editing tool<\/a>.<\/p>\n\n\n\n<p>Leave me a comment if you found this helpful, or you found something I could do better!<\/p>\n\n\n\n<p>Cheers!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>9 minute reading time; ~1720 words Welcome and hello! This post is going to take the work we&#8217;ve done so far, and put it where it can be used. We&#8217;re going to walk through designing an automated deployment process, and some cleanup that we have to do around the branding as part of taking it [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21],"tags":[43,42,40,25,26,44,34,19],"class_list":["post-842","post","type-post","status-publish","format-standard","hentry","category-software-engineering","tag-automation","tag-deployment","tag-github","tag-laravel","tag-php","tag-pipeline","tag-software","tag-tailgunner"],"_links":{"self":[{"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/posts\/842","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/comments?post=842"}],"version-history":[{"count":55,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/posts\/842\/revisions"}],"predecessor-version":[{"id":940,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/posts\/842\/revisions\/940"}],"wp:attachment":[{"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/media?parent=842"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/categories?post=842"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bendauphinee.com\/writing\/wp-json\/wp\/v2\/tags?post=842"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}