❤️ AZDIGI has officially updated to a new blog system. However, some posts may have incorrect or mismatched images. Please click the Report article button at the bottom of the post so AZDIGI can update as quickly as possible. Thank you!

After static sites, the next step is deploying backend applications: Node.js, Python, PHP. Coolify supports all of them via Nixpacks or Dockerfile, along with environment variables, health checks, and persistent storage.

📖 Previous article: Part 5, Deploy Static Site & SPA

I. Deploy Node.js Application

Express.js App

Create new resource → Public Repository → paste Node.js repo URL. Nixpacks auto-detects from package.json.

Example minimal package.json:

{
  "name": "my-api",
  "scripts": {
    "start": "node index.js",
    "build": "echo 'no build needed'"
  },
  "dependencies": {
    "express": "^4.18.0"
  }
}

And index.js:

const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;

app.get('/', (req, res) => { res.json({ message: 'Hello from Coolify!', time: new Date() }); });

app.get('/health', (req, res) => { res.status(200).json({ status: 'ok' }); });

app.listen(PORT, '0.0.0.0', () => { console.log(`Server running on port ${PORT}`); });

⚠️ App must listen on 0.0.0.0 (not localhost or 127.0.0.1), Docker containers need to bind all interfaces for proxy traffic to reach them.

Important Configuration

  • Ports Exposes: Port app listens on (e.g., 3000). Nixpacks usually auto-detects
  • Start Command: npm start (from package.json scripts.start)
  • Environment Variables: Add in “Environment Variables” tab: NODE_ENV=production, database URLs, API keys…

II. Deploy Python Application

Flask App

Nixpacks detects Python from requirements.txt or Pipfile.

# app.py
from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/') def home(): return jsonify({"message": "Hello from Flask on Coolify!"})

@app.route('/health') def health(): return jsonify({"status": "ok"})

if __name__ == '__main__': app.run(host='0.0.0.0', port=int(os.environ.get('PORT', 5000)))
# requirements.txt
flask==3.0.0
gunicorn==21.2.0

💡 Use gunicorn for production instead of Flask dev server. Nixpacks auto-detects gunicorn in requirements.txt and uses it as start command: gunicorn app:app.

Django App

Django requires additional config:

  • ALLOWED_HOSTS = ['*'] or specific domain in settings.py
  • STATIC_ROOT and run collectstatic in build command
  • Database URL via environment variable (DATABASE_URL)

III. Deploy PHP Application (Laravel)

Nixpacks supports PHP and Laravel natively. Detects from composer.json.

# Nixpacks auto-runs:
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan view:cache

Required configuration:

  • Environment variables: APP_KEY, APP_URL, DB_*
  • Persistent storage for /storage directory
  • Queue worker (if used): create separate resource for php artisan queue:work

IV. Build Packs – Comparison

Build PackWhen to useProsCons
NixpacksMost appsAuto-detect, zero configSometimes detects wrong version
DockerfileCustom build processFull controlMust write Dockerfile
Docker ImagePre-built image on registryFast, no buildMust build image yourself
Docker ComposeMulti-container appsMultiple services at onceMore complex config
Deploy Docker Image on Coolify
Deploy using Docker Image – enter image name (nginx:alpine) and deploy.
Node.js application configuration page on Coolify
Configuration page – set domain, port, build pack, build/start commands.

V. Environment Variables

Each resource has “Environment Variables” tab: add key-value pairs:

# Example environment variables
NODE_ENV=production
DATABASE_URL=postgresql://user:pass@db:5432/mydb
REDIS_URL=redis://redis:6379
API_KEY=sk-xxx
PORT=3000

ℹ️ Variables can reference other databases within the same Coolify instance. When creating a database, Coolify provides internal connection string using Docker network, no need to expose port externally.

VI. Health Checks

Health checks help Coolify know if app is running correctly:

  • Configure in resource → Health Check tab
  • Set Health Check Path: /health or /api/health
  • Coolify sends requests to this endpoint periodically: if doesn’t return 200, container gets restarted
  • Useful for zero-downtime deployment: new container must be healthy before shutting down old container

VII. Persistent Storage

By default, data in containers is lost on restart. Use Persistent Storage for data that needs to persist:

  • Go to resource → “Storages” tab
  • Add mount: Source (path on host) → Destination (path in container)
  • Example: /data/uploads/app/uploads

⚠️ Volumes are tied to specific server, if moving app to different server, data doesn’t auto-migrate. Backup before migrating!

Environment with multiple resources on Coolify
Production environment – showing deployed apps, databases, services.
Server Resources on Coolify
Resources tab – list of all containers running on server.

VIII. Summary

Deploying backend apps on Coolify is as simple as frontend, Nixpacks handles most things automatically. Key points: app must bind to 0.0.0.0, set environment variables, and use health checks for production. Next article: Docker Compose for complex applications.

Share:
This article has been reviewed by AZDIGI Team

About the author

Trần Thắng

Trần Thắng

Expert at AZDIGI with years of experience in web hosting and system administration.

10+ years serving 80,000+ customers

Start your web project with AZDIGI