A coding assistant drafted my Nginx config. Here’s what I still had to verify
Ardiansyah SulistyoDEV Community
2 views
I asked a coding assistant to draft an Nginx config for a small Laravel app on an Ubuntu VPS.
It produced something usable in seconds.
That is the useful part. The dangerous part is that a config can look completely reasonable, pass a quick visual scan, and still be wrong for the actual server.
The assistant does not know my installed PHP version, the PHP-FPM socket on the machine, my directory layout, whether DNS already points at the VPS, or which headers my app and proxy setup need. It can make sensible guesses. Production infrastructure is where sensible guesses need to become verified facts.
This is the review process I use before I let an AI-drafted Nginx config anywhere near a live site.
The starting point
The setup is intentionally boring:
Ubuntu VPS.
Nginx as the public web server.
A Laravel app in /var/www/myapp.
PHP-FPM handling PHP requests.
A non-root deploy user owning the app code.
A typical AI-generated starting point looks roughly like this:
server {
listen 80;
server_name example.com www.example.com;
root /var/www/myapp/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
}
There is nothing obviously bad about it. In fact, this is close to what I would write manually.
But “close” is not the same as correct.
1. I verify the document root
For Laravel, the Nginx root must point to the public directory:
root /var/www/myapp/public;
Not:
root /var/www/myapp;
This is an easy detail for an assistant to get right, but I still check it because a wrong root can expose files that should never be served publicly: .env, source code, Composer files, or internal directories.
On the server, I verify the path exists and contains Laravel’s entry point:
ls -la /var/www/myapp/public
I expect to see index.php there.
I also check the app’s actual deployment path instead of assuming it matches the example. A config generated for /var/www/app does not magically become correct because I pasted it into a file named myapp.
2. I verify the actual PHP-FPM socket
This is probably the most common “looks fine but returns 502” problem.
An assistant may assume:
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
But the server might have PHP 8.1, 8.3, or a custom pool/socket configuration.
Before using the config, I check what exists:
ls -la /run/php/
I might see:
php8.3-fpm.sock
php8.3-fpm.pid
In that case, the Nginx config needs:
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
I also confirm PHP-FPM itself is healthy:
sudo systemctl status php8.3-fpm
The exact service name depends on the installed version. This is why I do not trust a hard-coded PHP version from an AI response, a blog post, or an old config copied from another VPS.
3. I verify server_name and the default site
A correct server block can still be ignored if Nginx does not match the incoming host header.
I check the intended domains:
server_name example.com www.example.com;
Then I make sure the DNS records point to the VPS before treating the domain test as meaningful.
I also disable the default Nginx site once my own server block is ready:
sudo rm /etc/nginx/sites-enabled/default
That is optional if I deliberately want the default site, but leaving it enabled has confused me more than once during initial setup. A request can hit the default virtual host instead of the app and make it look as though the app config is broken.
To inspect what Nginx is actually loading, I use:
sudo nginx -T
For a faster targeted check:
sudo nginx -T | grep -A 15 'server_name example.com'
That is more useful than staring at the file I intended to enable. The effective configuration is what matters.
4. I verify the Laravel routing rule
This line is the core of a normal Laravel Nginx setup:
try_files $uri $uri/ /index.php?$query_string;
It lets Nginx serve real static files directly and forwards routes that do not map to files into Laravel’s front controller.
Without it, routes such as:
https://example.com/dashboard
https://example.com/settings/profile
can return 404 even though they work locally through Laravel’s development server.
I test at least:
The home page.
One regular application route.
A static asset such as CSS or an image.
A route with query parameters, if the app uses them.
A generated config can be syntactically valid and still miss the behavior the framework expects.
5. I verify ownership and writable directories
Nginx does not run Laravel alone. PHP-FPM executes PHP requests, and Laravel needs write access to some directories.
For a typical Laravel deployment, I check:
sudo chown -R deploy:deploy /var/www/myapp
sudo chmod -R ug+rwx /var/www/myapp/storage /var/www/myapp/bootstrap/cache
The right ownership model depends on how PHP-FPM is configured on the server. I do not treat the commands above as universal copy-paste instructions.
What I actually verify is:
Which user owns the application files.
Which user/group PHP-FPM workers run as.
Whether the application can write to storage/ and bootstrap/cache/.
Whether I have accidentally made the whole project world-writable just to make an error disappear.
If Laravel shows a generic 500 error after Nginx is configured, I check the Laravel log before changing random Nginx directives:
sudo tail -n 100 /var/www/myapp/storage/logs/laravel.log
A permissions issue often looks like an application error, not an Nginx error.
6. I add proxy headers only when the app is behind a proxy
For a Laravel app served directly by PHP-FPM, I do not need a proxy_pass block.
For a Node app behind Nginx, I do. The basic pattern is:
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Those headers are not decorative. They affect what the application sees as the request host, client address, and original scheme.
I check whether the app needs to trust its proxy before assuming HTTPS URLs, redirects, or secure cookies will behave correctly. This is especially important if TLS terminates at Nginx or another layer in front of the app.
7. I do not let the assistant “solve” TLS by guessing
The first Nginx config often listens on HTTP only:
listen 80;
That is fine as an initial step. It is not the final state for a public application that handles login or user data.
I usually get HTTP working first, then configure TLS with a certificate provider such as Let’s Encrypt. The exact commands and configuration depend on the domain, DNS state, firewall rules, and whether another proxy/CDN is involved.
This is a good example of where an AI response can be dangerously confident. It may tell you to paste a certificate path that does not exist yet, redirect all traffic before certificate issuance succeeds, or assume a particular Certbot setup.
My rule is simple: treat the TLS instructions as a plan to verify, not a deployment command to paste blindly.
8. I test before every reload
Before I reload Nginx, I run:
sudo nginx -t
If it passes:
sudo systemctl reload nginx
Then I test the response:
curl -I http://example.com
Once HTTPS is configured:
curl -I https://example.com
I also keep an eye on logs while testing:
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
For an app-specific setup, I prefer separate logs:
access_log /var/log/nginx/myapp-access.log;
error_log /var/log/nginx/myapp-error.log;
Then I can debug one site without digging through unrelated traffic from every server block.
What AI was actually useful for
The coding assistant was useful as a fast first draft. It helped me get a standard config shape without opening old repositories or searching for a template.
It was less useful as an authority on the live server.
The work that still mattered was:
Matching paths to the actual deployment.
Checking the installed PHP-FPM version and socket.
Confirming DNS and Nginx virtual-host selection.
Verifying application permissions.
Testing framework routes, static files, and error behavior.
Reading the actual server and application logs.
That is not a criticism of coding assistants. It is just the boundary I try to keep clear: they can draft infrastructure configuration, but they cannot know my machine better than the machine itself.
My small review checklist
Before I accept an AI-drafted Nginx config for a Laravel app, I check:
Does root point to the Laravel public/ directory?
Does fastcgi_pass match a real PHP-FPM socket on this server?
Does server_name match the actual domain, and does DNS point here?
Is the intended site enabled, and is a default site catching my request instead?
Does try_files route application URLs through index.php?
Can the app write to storage/ and bootstrap/cache/ without unsafe permissions?
Did I run sudo nginx -t before reloading?
Did I test a real request and inspect the relevant logs?
Is TLS configured and verified before I treat the site as ready?
The assistant can write the first 80% of a config in a few seconds. The remaining 20% is where production incidents tend to hide.
What infrastructure changes do you let coding assistants make directly, and what do you always verify by hand?
Originally published at nlocoding.com
38% of new APIs built in 2025 were designed, tested, or maintained by AI-enabled dev tools. Not by humans working solo. Not even close.
The API economy is moving. Fast. Two years ago, few teams trusted AI to write production code. In 2026, 61% of backend te
Originally published on tamiz.pro.
The Vanishing Act
AI agents vanish in production for three reasons: stateful sessions time out, dependencies bloat the runtime, and costs spiral silently. This guide fixes all three with minimal infra.
Prerequisites
Node.js 18+ or Python 3.
Vergessen Sie Hub-and-Spoke! Ihr klassisches VPN-Design ist ein Relikt aus einer Zeit, in der Bandbreite teuer und Ausfallsicherheit ein Luxus war. Heute ist ein zentraler VPN-Server, durch den der gesamte Traffic gequetscht wird, nichts weiter als ein selbstgebauter Flaschenhals und ein gigantische