Web Server Config Generator (Nginx & Apache)
Build a production-ready Nginx server block or Apache .htaccess file from a few choices: HTTPS and www redirects, static sites, single-page apps, PHP-FPM (Laravel, WordPress) or a reverse proxy to Node.js, plus gzip, browser caching and security headers.
Private by design: anything you enter is processed in your browser only. It is never uploaded to or logged on our servers. The config is generated locally; share links contain only the options you chose.
Domain
Site
For Laravel point this at the public directory, never the project root.
A Unix socket (unix:/run/php/php8.3-fpm.sock on Debian/Ubuntu) or 127.0.0.1:9000.
TLS (nginx only)
Leave empty for the Let's Encrypt (certbot) defaults under /etc/letsencrypt/live/<domain>/.
Performance
Security
About Nginx server blocks and Apache .htaccess files
Nginx and Apache serve most of the web, but they are configured very differently. Nginx uses server blocks stored in /etc/nginx/sites-available/ (Debian/Ubuntu) or /etc/nginx/conf.d/ (RHEL, the official nginx packages and Docker images) and loaded once at startup, so every change needs nginx -t and a reload. Apache can read per-directory .htaccess files on every request, which is why shared hosting relies on them: you can change redirects, headers and caching without root access, provided the virtual host sets AllowOverride.
The generated Nginx config follows common production practice: one block redirects HTTP to HTTPS, a second redirects the non-canonical host (www or non-www) so search engines see a single URL, and the main block serves the site. Security headers are set with the always flag so they are also sent on error pages. One nginx gotcha is that add_header inside a location replaces every header inherited from the server block, so the generator uses expires for asset caching and never adds headers inside locations.
A .htaccess file can only contain directives allowed in per-directory context. That covers mod_rewrite redirects, mod_headers, mod_expires and mod_deflate, each wrapped in <IfModule> so a missing module doesn't cause a 500 error. TLS certificates (SSLCertificateFile), HTTP/2 (Protocols h2 http/1.1) and ProxyPass must go in the <VirtualHost>. Note that apachectl configtest does not read .htaccess files; a mistake there shows up as a 500 response and a line in the error log.
Roll out HSTS carefully: once a browser has seen Strict-Transport-Security it refuses plain HTTP for the whole max-age, so start with a short value, and only add includeSubDomains when every subdomain has a valid certificate. For a full Content-Security-Policy header, build one with the CSP header builder and paste its nginx or Apache line into this config. Control crawlers with the robots.txt generator, and set up mail for the same domain with the SPF, DKIM & DMARC generator.
Reference Guide
Test and reload
| Task | Nginx | Apache |
|---|---|---|
| Test syntax | sudo nginx -t | sudo apachectl configtest (does not check .htaccess) |
| Apply changes | sudo nginx -t && sudo systemctl reload nginx | sudo systemctl reload apache2 (httpd on RHEL); .htaccess changes apply immediately |
| Enable a site | sudo ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/ | sudo a2ensite example.com |
| Enable modules | Built in (gzip, headers, rewrite) | sudo a2enmod rewrite headers expires deflate |
| Get a certificate | sudo certbot --nginx -d example.com -d www.example.com | sudo certbot --apache -d example.com -d www.example.com |
| Error log | /var/log/nginx/error.log | /var/log/apache2/error.log (/var/log/httpd/ on RHEL) |
Where config files live
| Setup | Location |
|---|---|
| Nginx on Debian/Ubuntu | /etc/nginx/sites-available/, symlinked into /etc/nginx/sites-enabled/ |
| Nginx on RHEL, Alpine, official packages, Docker | /etc/nginx/conf.d/*.conf (included automatically) |
| Apache virtual hosts | /etc/apache2/sites-available/ (Debian) or /etc/httpd/conf.d/ (RHEL) |
| .htaccess | Document root; the vhost <Directory> block needs AllowOverride All |
| Let's Encrypt certificates | /etc/letsencrypt/live/<domain>/fullchain.pem and privkey.pem |
How nginx picks a location block
| Step | Modifier | Behaviour |
|---|---|---|
| 1 | location = /path | Exact match. If it matches, the search stops immediately. |
| 2 | location ^~ /prefix/ | The longest matching prefix is remembered. If that prefix has ^~, regular expressions are skipped. |
| 3 | location ~ regex / ~* regex | Regexes (~ case-sensitive, ~* case-insensitive) are tested in the order they appear; the first match wins. |
| 4 | location /prefix | If no regex matched, the longest prefix from step 2 is used. |
Directive cheat sheet
| Nginx | Apache | Purpose |
|---|---|---|
return 301 https://$host$request_uri; | RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE] | Permanent redirect |
try_files $uri $uri/ /index.html; | RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule . /index.html [L] | Front controller / SPA fallback |
add_header Name "value" always; | Header always set Name "value" | Response header, also on errors |
expires 30d; | ExpiresByType text/css "access plus 30 days" | Browser caching (Expires + Cache-Control) |
gzip on; gzip_types …; | AddOutputFilterByType DEFLATE … | Compression |
client_max_body_size 20M; | LimitRequestBody 20971520 (bytes) | Upload size limit |
error_page 404 /404.html; | ErrorDocument 404 /404.html | Custom error page |
proxy_pass http://127.0.0.1:3000; | ProxyPass / http://127.0.0.1:3000/ (vhost only) | Reverse proxy |
location ~ /\.(?!well-known) { deny all; } | RewriteRule (^|/)\.(?!well-known/) - [F] | Hide dotfiles |
mod_rewrite flags: L last rule, R=301 permanent redirect, NE don't re-escape the URL, F 403 Forbidden, NC case-insensitive condition, OR combine conditions with OR.
Example input
domain: example.com · redirect www → non-www · HTTPS on site type: PHP-FPM (Laravel), root /var/www/example.com/public HTTP/2, gzip, 30-day asset caching, HSTS 1 year, nosniff, SAMEORIGIN, strict-origin-when-cross-origin, block dotfiles, 20M uploads
This sample loads automatically when you open the tool. Use Load Sample to bring it back.
Frequently Asked Questions
On Debian and Ubuntu save it as /etc/nginx/sites-available/<domain>.conf and symlink it into sites-enabled; on other systems use /etc/nginx/conf.d/<domain>.conf. Run nginx -t to test it, then reload Nginx.
Certificates, ports and HTTP/2 are server-level settings that Apache only accepts in the main config or a VirtualHost. An .htaccess file can force HTTPS with a redirect and add headers, but the certificate itself must be configured by the host.
Choose the SPA site type. It adds a fallback (try_files in Nginx, a rewrite in Apache) that serves index.html for unknown paths, so client-side routes like /dashboard load instead of returning 404.
Related Tools
All DevOps Tools →CSP Header Builder
Build a Content-Security-Policy header directive by directiv...
SPF, DKIM & DMARC Record Generator
Generate and check SPF, DKIM and DMARC DNS TXT records for e...
Dockerfile Linter
Lint a Dockerfile for security and best-practice issues: unp...
Automatic Schema OCR Extractor
Upload a PDF or image to automatically match keywords and ex...
Generic OCR Data Extractor
Interactively draw crop zones over templates to design reusa...
Full JSON Layout Extractor (Raw OCR)
Perform raw OCR on documents to extract full text lines, str...