GreenCrew blog

Uptime literacy for founders.

What a health check can see, how to tell customers when it cannot, and the boring failures — DNS, certificates, domains — that take a product offline without a red deploy.

How to Build a Node.js Application with Docker (Dockerfile, .dockerignore, and Docker Compose)

To build a Node.js application with Docker, write a Dockerfile that starts FROM node:24-alpine, copies package*.json, runs npm ci --omit=dev, copies your code, switches to USER node, and ends with CMD ["node", "server.js"], then run docker build -t myapp . and docker run -p 3000:3000 myapp. This guide covers .dockerignore, multi-stage builds, health checks, graceful shutdown, Docker Compose with PostgreSQL, and putting Nginx in front.

Node.jsDockerDocker ComposeNginxDevOps·

greencrew

How to Install Node.js on Ubuntu (apt, NodeSource, and nvm Compared)

To install a current LTS version of Node.js on Ubuntu, add the NodeSource repository with curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash - and run sudo apt install -y nodejs, or install nvm and run nvm install --lts for per-user version switching. This guide compares apt, NodeSource, and nvm, then covers npm global packages, build tools, switching versions, and uninstalling Node.js.

Node.jsUbuntunpmnvmLinuxDevOps·

greencrew

How to Install a LOMP Stack on Ubuntu (OpenLiteSpeed, MariaDB, and PHP Step by Step)

To install a LOMP stack on Ubuntu, add the LiteSpeed repository with wget -O - https://repo.litespeed.sh | sudo bash, run sudo apt install openlitespeed lsphp83 lsphp83-mysql mariadb-server, set the WebAdmin password with admpass.sh, and point the lsphp external app at the PHP version you installed. This guide covers every step, including virtual hosts, port 80, a MariaDB user, Let's Encrypt SSL, and troubleshooting.

OpenLiteSpeedMariaDBPHPLOMPLinuxDevOps·

greencrew

How to Install Strapi for Production on Ubuntu (PostgreSQL, PM2, Nginx, and HTTPS)

To run Strapi in production on Ubuntu, create the project with npx create-strapi@latest, point it at PostgreSQL through DATABASE_CLIENT=postgres in .env, build the admin panel with NODE_ENV=production npm run build, start it with PM2, and proxy a domain to port 1337 with Nginx. This guide covers each step, plus HTTPS with Certbot, upload limits, the first admin account, updates, and troubleshooting.

StrapiNode.jsPostgreSQLNginxPM2DevOps·

greencrew

How to Scale Node.js Applications with Clustering (cluster Module, Load Testing, and Zero-Downtime Restarts)

To scale a Node.js application across CPU cores, use the built-in node:cluster module: in the primary process call cluster.fork() once per os.availableParallelism(), and let each worker run your HTTP server on the same port. This guide covers a complete cluster script, restarting crashed workers, load testing with autocannon, zero-downtime rolling restarts, shared state with Redis, sticky sessions, and PM2 or Nginx alternatives.

Node.jsClusterPerformanceNginxScalingDevOps·

greencrew

How to Set Up a Local PHP Development Environment on Ubuntu (php -S Built-In Server, Xdebug, and Composer)

To set up a local PHP development environment on Ubuntu, run sudo apt install php-cli php-mbstring php-xml php-curl php-zip php-sqlite3 unzip, enable development error settings, and start a project with php -S localhost:8000 -t public. This guide covers the built-in web server, Xdebug step debugging in VS Code, Composer, a local database, and when to switch to Nginx with PHP-FPM.

PHPUbuntuXdebugComposerNginxDevOps·

greencrew

How to Use Multithreading in Node.js (worker_threads, Worker Pools, and When to Use Them)

To use multithreading in Node.js, import Worker from node:worker_threads, move CPU-heavy code into a separate worker file, and exchange data with postMessage and the message event so the main event loop stays free. This guide covers a blocking-vs-worker example, a promise wrapper, worker pools with Piscina, sharing memory, the libuv thread pool, and when to use cluster instead.

Node.jsworker_threadsPerformanceJavaScriptDevOps·

greencrew

How to Use Sequelize with Node.js and MySQL (Models, Migrations, Associations, and Queries)

To use Sequelize with Node.js and MySQL, run npm install sequelize mysql2, create a connection with new Sequelize(database, user, password, { host: 'localhost', dialect: 'mysql' }), check it with sequelize.authenticate(), and define models with sequelize.define(). This guide covers creating the MySQL user, sequelize-cli migrations and seeders, CRUD queries, operators, associations, transactions, and common connection errors.

Node.jsSequelizeMySQLORMJavaScriptDevOps·

greencrew

How to Install and Secure phpMyAdmin with Nginx on Ubuntu (Custom URL, Basic Auth, and No Root Login)

To run phpMyAdmin with Nginx on Ubuntu, install it with sudo apt install phpmyadmin, choose no web server when the installer asks for Apache or lighttpd, and serve /usr/share/phpmyadmin from an Nginx location block on a hard-to-guess path that passes PHP to PHP-FPM. Then lock it down with HTTPS, HTTP basic auth, an IP allowlist, and a dedicated MySQL user instead of root. This guide covers the full config, every security layer, and fixes for common phpMyAdmin errors.

NginxphpMyAdminMySQLPHPSecurityDevOps·

greencrew

How to Install and Use Composer on Ubuntu (Verified Global Install, composer.json, and Production Deploys)

To install Composer on Ubuntu, install php-cli and unzip, download the installer from getcomposer.org, verify its SHA-384 hash against composer.github.io/installer.sig, and run php composer-setup.php --install-dir=/usr/local/bin --filename=composer so the composer command works globally. This guide covers the verified install script, require vs install vs update, composer.lock, autoloading, version constraints, production deploys with --no-dev, and common Composer errors.

PHPComposerUbuntuLinuxNginxDevOps·

greencrew

How to Install PHP on Ubuntu and Run Multiple Versions (ondrej/php PPA, update-alternatives, and PHP-FPM per Site)

To install a specific PHP version on Ubuntu, add the ondrej/php PPA with sudo add-apt-repository ppa:ondrej/php, then install versioned packages like php8.4-fpm and php8.2-fpm side by side. Switch the CLI version with sudo update-alternatives --config php, and point each Nginx site at its own socket, such as fastcgi_pass unix:/run/php/php8.2-fpm.sock. This guide covers extensions, php.ini locations, Composer, upgrading a site, and common errors.

NginxPHPPHP-FPMUbuntuLinuxDevOps·

greencrew

How to Set Up Laravel, Nginx, and MySQL with Docker Compose (Dockerfile, nginx.conf, and .env)

To run Laravel with Docker Compose, define three services: app (a php:8.3-fpm image with pdo_mysql), nginx (with fastcgi_pass app:9000 and root /var/www/html/public), and mysql (with a named volume), then set DB_HOST=mysql in Laravel's .env. This guide gives you the full docker-compose.yml, Dockerfile, and Nginx config, plus migrations, queue workers, the scheduler, production notes, and fixes for common errors.

NginxLaravelDockerMySQLPHPDevOps·

greencrew

How to Deploy Django with PostgreSQL, Gunicorn, and Nginx on Ubuntu (systemd Socket and Static Files)

To deploy Django in production, run it with Gunicorn under a systemd socket at /run/gunicorn.sock, point Nginx at it with proxy_pass http://unix:/run/gunicorn.sock;, serve collected static files with an alias location, and store data in PostgreSQL. This guide covers the Postgres database, virtualenv, production settings, collectstatic, systemd units, HTTPS, and fixing 502, 400, and CSRF errors.

NginxDjangoPythonPostgreSQLGunicornDevOps·

greencrew

How to Deploy Laravel with Nginx on Ubuntu (Server Block, Permissions, Queues, and Scheduler)

To deploy Laravel with Nginx, set the server block's root to your app's public/ directory, add try_files $uri $uri/ /index.php?$query_string; to the location / block, pass index.php to PHP-FPM, and give www-data write access to storage/ and bootstrap/cache. This guide covers PHP extensions, Composer, the .env file, caching, migrations, queue workers, the scheduler, HTTPS, and common Laravel 404/500 errors.

NginxLaravelPHPLinuxDevOps·

greencrew

How to Deploy a NestJS Application with Nginx on Ubuntu (Build, PM2, Health Checks, and HTTPS)

To deploy a NestJS app, run npm run build to compile TypeScript into dist/, start dist/main.js with PM2 on 127.0.0.1:3000, and put Nginx in front with proxy_pass http://127.0.0.1:3000. This guide covers main.ts production settings (trust proxy, shutdown hooks, global prefix), environment config, a Terminus health check, WebSocket gateways, HTTPS, and common NestJS deployment errors.

NginxNestJSNode.jsTypeScriptDevOps·

greencrew

How to Self-Host n8n with Docker and Nginx (Docker Compose, WebSockets, SSL, and WEBHOOK_URL)

To self-host n8n, run the docker.n8n.io/n8nio/n8n image with Docker Compose bound to 127.0.0.1:5678, set N8N_HOST, N8N_PROTOCOL=https, and WEBHOOK_URL, then put Nginx in front with proxy_pass http://127.0.0.1:5678 plus WebSocket Upgrade headers and a Let's Encrypt certificate. This guide covers the compose file, PostgreSQL, the encryption key, backups, updates, and fixing secure cookie, WebSocket, and webhook URL errors.

Nginxn8nDockerAutomationDevOps·

greencrew

How to Deploy a React App with Nginx on Ubuntu (try_files for React Router, Caching, and API Proxy)

To deploy a React app with Nginx, run npm run build, copy the build folder (dist for Vite) to /var/www/your-app, and add a server block with root pointing at it and try_files $uri $uri/ /index.html so React Router routes don't return 404. This guide covers the full config, caching hashed assets, proxying /api to a backend, subfolder deploys, and HTTPS.

NginxReactViteFrontendDevOps·

greencrew

How to Fix ERR_SSL_PROTOCOL_ERROR in Nginx ("This Site Can't Provide a Secure Connection")

ERR_SSL_PROTOCOL_ERROR usually means the server answered an HTTPS request with plain HTTP, most often because the Nginx server block says listen 443 without the ssl parameter. Change it to listen 443 ssl, point ssl_certificate and ssl_certificate_key at a valid certificate, and run nginx -t && systemctl reload nginx. This guide covers every server-side and client-side cause, how to diagnose each with curl and openssl, and how to prevent it.

NginxSSLTLSTroubleshootingDevOps·

greencrew

How to A/B Test with Nginx (split_clients, Sticky Cookies, and Variant Logging)

To A/B test with Nginx, use split_clients "${remote_addr}${http_user_agent}" $variant { 50% "a"; * "b"; } in the http block, then route each variant to a different root or upstream and log $variant in your access log. This guide covers sticky cookies, targeting users by device, country, or language, measuring conversions from logs, and avoiding SEO and caching mistakes.

NginxA/B TestingAnalyticsTraffic SplittingDevOps·

greencrew

How to Create a Self-Signed SSL Certificate for Nginx (openssl Command, Nginx Config, and Trusting It)

To create a self-signed certificate for Nginx, run openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout nginx-selfsigned.key -out nginx-selfsigned.crt with a subjectAltName, then point ssl_certificate and ssl_certificate_key at the files in a listen 443 ssl server block. This guide covers the full config, the HTTP-to-HTTPS redirect, trusting the certificate on Linux and macOS, mkcert, and fixing browser errors.

NginxSSLTLSOpenSSLDevOps·

greencrew

How to Add Security Headers in Nginx (HSTS, CSP, X-Frame-Options, and More)

To add security headers in Nginx, use add_header with the always flag, for example add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; put them in a shared snippet so add_header inheritance doesn't drop them, then reload and verify with curl -I. This guide covers HSTS, Content-Security-Policy, X-Content-Type-Options, frame protection, Referrer-Policy, and Permissions-Policy.

NginxSecurityHTTP HeadersTLSDevOps·

greencrew

How to Set Up Nginx Caching with proxy_cache (Config, Cache Bypass, and Serving Stale Content)

To set up Nginx caching, define a cache with proxy_cache_path /var/cache/nginx/app levels=1:2 keys_zone=app_cache:10m max_size=1g inactive=60m; in the http block, then add proxy_cache app_cache; and proxy_cache_valid 200 10m; to your proxied location. This guide covers the full config, cache bypass for logged-in users, microcaching, serving stale content when the backend is down, and purging.

NginxCachingPerformanceReverse ProxyDevOps·

greencrew