<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bokor Attila</title>
    <description>The latest articles on DEV Community by Bokor Attila (@battila).</description>
    <link>https://dev.to/battila</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3884073%2F2f42b8fa-3437-40ce-9208-5c8fadfb15dd.png</url>
      <title>DEV Community: Bokor Attila</title>
      <link>https://dev.to/battila</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/battila"/>
    <language>en</language>
    <item>
      <title>Automating Laravel Sail Setup: From Tedious to Trivial</title>
      <dc:creator>Bokor Attila</dc:creator>
      <pubDate>Sun, 15 Feb 2026 08:31:22 +0000</pubDate>
      <link>https://dev.to/battila/automating-laravel-sail-setup-from-tedious-to-trivial-10o</link>
      <guid>https://dev.to/battila/automating-laravel-sail-setup-from-tedious-to-trivial-10o</guid>
      <description>&lt;p&gt;Laravel Sail setup: from 15 minutes of tedious work to 30 seconds with one command. Here's how I did it.&lt;/p&gt;

&lt;p&gt;I use Laravel Sail for my local development, but for every project I have the same setup with small changes so I don't get port conflicts. After doing this process countless times, I decided to automate it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Manual Process (The Old Way)
&lt;/h2&gt;

&lt;p&gt;Setting up a new Laravel project locally used to involve these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the existing project&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;.env.example&lt;/code&gt; into &lt;code&gt;.env&lt;/code&gt; file&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;DB_*&lt;/code&gt; access environment variables to the standard Sail ones&lt;/li&gt;
&lt;li&gt;Check my notes to see the last port number I used&lt;/li&gt;
&lt;li&gt;Set the &lt;code&gt;APP_PORT&lt;/code&gt; to the next one (for example, &lt;code&gt;8057&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Set all the other ports to follow the same logic, so I know when I want to connect to MySQL the port should be &lt;code&gt;3357&lt;/code&gt; for the current project, etc.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here's an example of my port configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;APP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8057
&lt;span class="nv"&gt;FORWARD_DB_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3357
&lt;span class="nv"&gt;FORWARD_REDIS_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;6357
&lt;span class="nv"&gt;FORWARD_MEILISEARCH_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;7757
&lt;span class="nv"&gt;FORWARD_MAILPIT_DASHBOARD_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;18157
&lt;span class="nv"&gt;FORWARD_MAILPIT_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1057
&lt;span class="nv"&gt;VITE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5157

&lt;span class="nv"&gt;SAIL_XDEBUG_MODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;develop,debug,coverage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I keep the last two digits consistent (57 in this case) across all ports, making them easy to remember and avoid conflicts.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Since there is no vendor folder yet, and my local PHP usually differs from the project needs, I run the official Laravel Docker composer install:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-u&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:/var/www/html"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-w&lt;/span&gt; /var/www/html &lt;span class="se"&gt;\&lt;/span&gt;
    laravelsail/php84-composer:latest &lt;span class="se"&gt;\&lt;/span&gt;
    composer &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-platform-reqs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I created an alias for this: &lt;code&gt;sailinit 84&lt;/code&gt; (this runs composer install with PHP 8.4 in the current folder)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the dependencies install, I run &lt;code&gt;sail up -d&lt;/code&gt; (I also made an alias for this: &lt;code&gt;sup&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Done! The project is locally working.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can see that this is really boring, especially if you have to set up a new Laravel project locally like once a week.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabnlx0jg4xb5wew76yn6.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fabnlx0jg4xb5wew76yn6.gif" width="220" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Automation
&lt;/h2&gt;

&lt;p&gt;After a while, I was looking up more and more ways to create aliases to automate parts of this setup. I was also experimenting with small Go scripts (nothing fancy, I was only starting to learn).&lt;/p&gt;

&lt;p&gt;After experimenting with Go a bit before, I knew that a Go program would definitely be perfect for this. The problem is that I was only just starting to learn Go. But that's where Google's Antigravity IDE came in handy. (I know Claude Code is probably better for this kind of stuff, but I just got 6 months of Google AI Pro free with my new phone and I'm going to squeeze every drop of value out of that subscription!) I started tinkering, and after about 2 hours of experimentation, I had a working program that automates this whole setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Flow
&lt;/h2&gt;

&lt;p&gt;Now the process is incredibly simple:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the existing project&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;cd&lt;/code&gt; into the project directory&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;sailinit&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Done!&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyr4qcapnlnmul12p86q.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiyr4qcapnlnmul12p86q.gif" width="400" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Power of Vibecoding
&lt;/h2&gt;

&lt;p&gt;I think vibecoding is really good for these kind of projects that have no real consequences. If it messes up something, it will be annoying, but nothing would happen with live projects or something only I will be annoyed to go back to manually setting up a project. :)&lt;/p&gt;

&lt;p&gt;The time saved adds up quickly, and the mental overhead of remembering port numbers and manual steps is completely gone. Sometimes the best solutions come from scratching your own itch.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Downside of Vibecoding
&lt;/h3&gt;

&lt;p&gt;Of course, there's a catch. Now I have this setup written in Go, and I'm not actually that good at Go development. If I need to modify something, I'll have to either learn Go properly or "vibecode" my way through it. The thing is, I wouldn't normally "vibecode" in a way where I don't fully understand what's happening but for throwaway tools like this? It's acceptable in my opinion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Want to try it yourself?&lt;/strong&gt; Check out the repository: &lt;a href="https://github.com/Bokor-Attila/Sailinit" rel="noopener noreferrer"&gt;Sailinit on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>sail</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
