Mar 30 2026

Deploying a full-stack application traditionally means juggling a lot of moving parts: provisioning a server, installing Docker, writing Nginx configs, setting up SSL renewal with Let's Encrypt, wiring up environment variables, and configuring a CI pipeline so every git push redeploys the app. Each of those is a learning curve on its own.
Coolify collapses all of that into a single self-hosted dashboard. It is an open-source platform that gives you a Heroku- or Vercel-style developer experience on infrastructure you own and pay for once, instead of per-app. You bring a Linux server (a Strettch Cloud Compute, in this case) and Coolify handles Docker, reverse proxying, automatic HTTPS, GitHub integration, and continuous deployment for you.
In this tutorial, you will deploy ShopEase, a full-stack ecommerce application, on a Strettch Cloud Compute using Coolify. ShopEase has three services:
Coolify runs each of these as a Docker container on the same Compute. It also runs Traefik, a reverse proxy that sits in front of every service. Traefik is what lets you have three subdomains (shopease.YOUR_DOMAIN, api.shopease.YOUR_DOMAIN, coolify.YOUR_DOMAIN) all served from a single Compute, each with its own free SSL certificate provisioned automatically by Let's Encrypt. You will not configure any of this by hand — Coolify does it for you the moment you set a domain on a service.
By the end of this guide, you will have:
mainThe whole setup takes about 30 minutes if everything goes smoothly, and most of that is waiting for builds to finish.
Architecture overview:

The browser only ever talks to Traefik on ports 80 and 443. Traefik then forwards each request to the right container based on the subdomain in the URL. The frontend talks to the API over the public internet (so the browser can reach it directly), while the API talks to MongoDB over Coolify's internal Docker network — MongoDB is never exposed to the public internet.
Before you begin, you will need the following. Each item links to the relevant background material if you are new to it.
root on your Compute over SSH. If you have never used SSH before, see DigitalOcean's SSH essentials guide. You do not need any prior Docker, Nginx, or Linux administration experience, Coolify handles all of that.Coolify needs a Linux server to run on. In Strettch Cloud terminology that's a Compute ~ a virtual machine you can SSH into. In this step you will provision one and connect to it. By the end you'll have a public IP address and a root shell ready for the Coolify installer.
When picking a plan in the Strettch Cloud dashboard, choose the configuration with the specs: 2 vCPU, 4 GB RAM, and 80 GB SSD running Ubuntu 24.04 LTS, with the Public IP add-on enabled so you can reach your Compute from the internet.
For a step-by-step walkthrough of the Strettch Cloud dashboard, see the Strettch Cloud quickstart guide.
Note: 4 GB of RAM is the recommended minimum. Coolify itself uses about 1.5 GB, and the Next.js Docker build process needs another 1.5–2 GB to compile pages. Computes with 2 GB of RAM will run Coolify fine but will fail during the frontend build in Step 7. If your budget is tight, you can resize up to 4 GB just for the build and resize back down afterward.
Once the Compute is ready, note your public IP address (referred to as YOUR_COMPUTE_IP throughout this tutorial, substitute your actual IP wherever you see it). Then open a terminal on your local machine and connect via SSH:
ssh root@YOUR_COMPUTE_IP -p 222
If the connection succeeds you will see a prompt similar to:
root@my-compute:~#
That confirms you're now working on the Compute, not on your local machine. You can run exit at any time to return to your local shell.
Note: Strettch Cloud Computes use SSH port
222instead of the standard port22due to a firewall restriction from Strettch Cloud's upstream internet provider. See the Strettch Cloud SSH access docs for the full explanation. If a connection on port22is refused, this is expected — always specify-p 222. If port222also hangs, your local network or firewall may be blocking outbound traffic on that port; try from a different network (mobile hotspot is a quick test).
Once you're connected, refresh the package index so the next step pulls the latest versions of any dependencies the Coolify installer asks for:
sudo apt-get update
This takes about 10 seconds on a fresh Compute. You only need to run it once before the Coolify installer.
In this step you will install Coolify on the Compute you just provisioned. Coolify ships a single-command installer that handles every dependency for you: Docker, Docker Compose, networking rules, the Coolify control panel itself, and a Postgres database that Coolify uses internally to track your projects. You won't run any of those steps manually.
The installer takes 2–5 minutes depending on your Compute's network speed. While it runs, it will print a numbered progress log so you can see what stage it's on.
Run the following command on your Compute (you should still be SSH'd in from Step 1):
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
The installation takes 2 to 5 minutes. You will see progress output as it completes each stage:
Step 1/9: Installing required packages
Step 2/9: Checking OpenSSH server configuration
Step 3/9: Checking Docker installation
...
Step 9/9: Installing Coolify
When it finishes, you will see a message like:
Your instance is ready to use!
You can access Coolify through your Public IPV4: http://YOUR_COMPUTE_IP:8000
That URL is the Coolify dashboard. Keep it handy, you'll open it in the next sub-step.
Note: If the installer fails with a
dpkg lockerror, the Compute is running background package updates (this is common right after a fresh provision). Wait a moment and retry with the snippet below, thewhileloop blocks until the lock is released:while fuser /var/lib/dpkg/lock-frontend >/dev/null 2>&1; do sleep 2; done curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
Now that Coolify is running, you'll create an admin account and your first project. The project is just a logical grouping ~ every service you deploy belongs to a project.
http://YOUR_COMPUTE_IP:8000 in your browser. The page may take a few seconds to load on first access while Coolify finishes booting.You should now see the Coolify dashboard with a project called "My first project" containing a "production" environment. If you see this, you're ready to move on. If the page is blank or stuck on a loading spinner, give it 10–20 seconds and refresh as Coolify is sometimes still finishing background setup.
You're doing DNS before deploying any services because Traefik (Coolify's built-in reverse proxy) provisions SSL certificates from Let's Encrypt the first time it sees a service with a domain attached. Let's Encrypt issues a certificate by hitting the domain over HTTP and verifying the response, which only works if DNS already points the domain at your Compute. Set DNS first and the rest of the tutorial will "just work."
You will create three subdomains, one per service.
Note: Throughout this tutorial, replace
YOUR_DOMAINwith your registered domain name wherever it appears in configuration values, commands, and URLs. For example, if you own[example.io](http://example.io), you'll end up with[shopease.example.io](http://shopease.example.io),[api.shopease.example.io](http://api.shopease.example.io), and[coolify.example.io](http://coolify.example.io).
In your domain registrar or DNS provider's dashboard, create three A records pointing to your Compute's IP address:
| Type | Name | Value | TTL |
|---|---|---|---|
| A | shopease | YOUR_COMPUTE_IP | 300 |
| A | api.shopease | YOUR_COMPUTE_IP | 300 |
| A | coolify | YOUR_COMPUTE_IP | 300 |
For example, if your domain is YOUR_DOMAIN, these records will create:
shopease.YOUR_DOMAIN : the Next.js frontendapi.shopease.YOUR_DOMAIN : the Express.js backend APIcoolify.YOUR_DOMAIN : the Coolify dashboardDNS propagation usually takes 1 to 5 minutes, but can occasionally take up to an hour depending on your registrar. You can verify a record is active by running dig from your local machine:
dig shopease.YOUR_DOMAIN +short
A working response looks like a single line with your Compute's IP, e.g.:
192.0.2.42
If dig returns nothing, the record hasn't propagated yet. Wait a minute and run it again. Don't move to the next step until all three subdomains resolve. If you do, the SSL certificate provisioning later will fail and you'll have to redeploy.
Note: If you don't have
diginstalled (it's missing on Windows by default), you can use https://dnschecker.org instead paste the subdomain in and confirm it returns your Compute's IP from multiple geographic regions.
For Coolify to deploy your code, it needs to read your repositories and listen for push events. Coolify supports several Git providers; this tutorial uses GitHub Apps, which is GitHub's recommended way to grant scoped, revocable access to a third-party tool. Compared to a personal access token, a GitHub App lets you grant access to specific repositories only and revoke access at any time without affecting your other tokens.
By the end of this step, Coolify will have read access to the two ShopEase repositories and a webhook will be installed on each so that pushes to main automatically redeploy.
You'll deploy your own forks (rather than the originals) so that you can push changes to them and watch Coolify redeploy. If you have not already, fork both project repositories to your GitHub account or organization:
Click the Fork button on each repository's GitHub page. You can keep the default name and description.
my-coolify). This is just a label so you can identify the connection later.coolify-express-apicoolify-nextjs-storeYou will be redirected back to Coolify. The GitHub source should now appear under Sources with a green/connected status indicator. If the page reloads but the source shows red or "Not connected," go back to GitHub at https://github.com/settings/installations and confirm the installation completed.
Note: If you need to grant access to additional repositories later, you can manage the GitHub App installation at
https://github.com/settings/installationswithout re-doing this whole flow.
You're deploying MongoDB first because the Express.js API needs a database connection string before it can start. Once MongoDB is running, Coolify will give you an internal connection URL ~ a hostname only reachable from other containers on the same Compute. You'll paste this URL into the API's environment variables in the next step.
This setup keeps MongoDB completely off the public internet. There's no external port, no firewall rule, no exposed credential to leak. The only thing that can talk to it is another container in the same Coolify project.
mongodb and select MongoDB under the Databases section. (Coolify supports several variants, pick the plain "MongoDB" one, version 7.)Coolify creates the database with auto-generated credentials. On the configuration page, you will see:
mongo:7root (auto-generated)mongodb://root:GENERATED_PASSWORD@CONTAINER_ID:27017/?directConnection=true
CONTAINER_ID part will be a short string like n58y4pvy, that's the hostname of the MongoDB container on Coolify's internal network.The first start pulls the mongo:7 Docker image (~700 MB) and initializes the database. Watch the status indicator at the top of the page. It will progress through "Starting" → "Running" → "Running (healthy)". Wait for the Running (healthy) state before proceeding. If it stays on "Starting" for more than 2 minutes, click the Logs tab to see what's happening (usually it's just slow image download on a fresh Compute).
Note: The internal URL uses a Docker container hostname, not
[localhost](http://localhost). If you tried to usemongodb://root:...@localhost:27017you'd get a connection refused error. Docker's networking doesn't work that way. Stick with the URL Coolify gives you.
Now you'll deploy the API. Three things happen in this step: Coolify clones your fork, builds the Docker image defined by the repo's Dockerfile, and starts the container behind Traefik with an SSL certificate. After the container is running, you'll seed the database with sample products so the storefront has something to show in Step 7.
You're deploying the API before the frontend because the frontend's build process bakes the API URL into its JavaScript bundle. The API needs to exist (and have data) before the frontend is built and rendered for visitors.
coolify-express-api repository.main branch.On the configuration page, update the following settings under General:
shopease-apihttps://api.shopease.YOUR_DOMAIN5000Warning: The Domain field must include the
https://prefix. For example, enterhttps://api.shopease.YOUR_DOMAIN, notapi.shopease.YOUR_DOMAIN. If you omit the protocol, Traefik will fail to route traffic to your application. You will see "404 page not found" errors, and SSL will not be provisioned. This is the single most common deployment mistake with Coolify.
MONGODB_URI=mongodb://root:GENERATED_PASSWORD@CONTAINER_ID:27017/shopease?authSource=admin&directConnection=true
JWT_SECRET=your-secret-key-change-this-to-something-random
PORT=5000
FRONTEND_URL=https://shopease.YOUR_DOMAIN
Note: The
MONGODB_URIvalue requires modification from the internal URL you copied in Step 5. Take the original URL and make two changes: add/shopeaseafter the port number to specify the database name, and replace the query string with?authSource=admin&directConnection=true. For example, if the internal URL ismongodb://root:abc123@n58y4pvy:27017/?directConnection=true, change it tomongodb://root:abc123@n58y4pvy:27017/shopease?authSource=admin&directConnection=true.
Click the Deploy button. Coolify will:
Dockerfile in the repo rootapi.shopease.YOUR_DOMAINThe whole process takes about 30 seconds. You can watch each stage live in the Deployment Logs panel that appears after you click Deploy.
Once the deployment succeeds, verify the API is responding by running this from your local machine:
curl https://api.shopease.YOUR_DOMAIN/api/health
You should see:
{"status":"ok","service":"shopease-api"}
If you get a curl: (6) Could not resolve host error, DNS hasn't propagated yet — wait a minute and retry. If you get a 404 page, the most likely cause is a missing https:// prefix in the Domain field, Go back and double-check it. If you get a "certificate has expired" or "self-signed certificate" error, Let's Encrypt couldn't issue the cert (usually because DNS wasn't ready when you deployed); redeploy from Coolify to retry.
The API now responds to /api/health, but if you call /api/products right now you'll get an empty array []. The database has no products in it yet. You need to seed it before the storefront will have anything to show. Skipping this step is the single most common reason the ShopEase frontend appears blank in Step 7.
The backend includes a seed script that inserts 10 sample products. The easiest way to run it is from inside Coolify:
shopease-api application page in Coolify.node src/seed.js
If you prefer working from SSH on the Compute, you can do the same thing with docker exec:
# Find the backend container name (skip Coolify's own containers and the Mongo one)
docker ps --format '{{.Names}}' | grep -v coolify | grep -v mongo
# Run the seed script (replace CONTAINER_NAME with the output of the line above)
docker exec CONTAINER_NAME node src/seed.js
Either way, you should see output like:
Connected to MongoDB
Cleared existing products
Seeded 10 products
Done!
Confirm the products are now available by hitting the API again:
curl https://api.shopease.YOUR_DOMAIN/api/products
This time you should see a JSON array with 10 product objects. If it's still empty, check the seed script's terminal output for an error, the most common cause is a malformed MONGODB_URI (revisit the Note in Setting Environment Variables above).
This is the last step. You'll deploy the storefront and point it at the API you set up in Step 6. The flow is identical to the API deployment with one important twist: Next.js needs the API URL at build time, not just at runtime, because it embeds the URL into the JavaScript bundle that ships to the browser. You'll see how to handle that with the Available at Buildtime checkbox below.
When this step completes, opening https://shopease.YOUR_DOMAIN in a browser will show the ShopEase storefront with the 10 products you seeded.
coolify-nextjs-store repository.main branch.On the configuration page, update the following settings under General:
shopease-storehttps://shopease.YOUR_DOMAIN3000Warning: As with the backend, the Domain field must include
https://. Enterhttps://shopease.YOUR_DOMAINnotshopease.YOUR_DOMAIN. Omitting the protocol will break Traefik routing and prevent SSL provisioning.
Click Save.
NEXT_PUBLIC_API_URL=https://api.shopease.YOUR_DOMAIN
NEXT_PUBLIC_API_URL has the Available at Buildtime checkbox enabled.Note: The
NEXT_PUBLIC_API_URLvariable must be available at build time because the Dockerfile usesARG NEXT_PUBLIC_API_URLto inject the API URL during the Next.js build process. Coolify enables this by default, but you should confirm it is checked. If you change this value later, you must redeploy (not just restart) the application for the change to take effect.
Click Deploy. The Next.js build is more resource-intensive than the backend and takes 1 to 2 minutes. During that time it will install dependencies, run TypeScript checks, compile all pages, generate static content, and create a standalone production image. You can watch progress in the Deployment Logs panel.
Note: If the build fails with
exit code 137, the Compute ran out of memory. This is what the Prerequisites note about 4 GB RAM was warning you about. Next.js builds can spike to 1.5–2 GB on their own. Resize the Compute to 4 GB if you're on a smaller plan.If the build fails with exit code 255, this is typically a transient Docker BuildKit issue. Click Redeploy to try again. If the error persists, clear the Docker build cache via SSH:
docker builder prune -f
Once deployment finishes, visit https://shopease.YOUR_DOMAIN in your browser. You should see the ShopEase storefront displaying all 10 products.
If the page loads but shows "0 products" or an empty grid, the frontend was built before the database was seeded, open the browser DevTools network tab to confirm: a 200 response with an empty [] body means seeding wasn't run, while a CORS error or failed request means NEXT_PUBLIC_API_URL was wrong at build time. Either way, the fix is to redeploy after correcting the underlying issue (re-seed, then Redeploy the frontend).
The errors below cover the failure modes most readers hit on a first deployment. If you run into something not listed here, the Logs tab in Coolify (per-service) is almost always the fastest way to diagnose.
| Symptom | Likely Cause | Fix |
|---|---|---|
curl: (6) Could not resolve host when hitting your API or storefront | DNS hasn't propagated yet | Wait 1–5 minutes and retry. Verify with dig <subdomain> +short or [dnschecker.org](https://dnschecker.org). |
| Browser shows "404 page not found" instead of your app | Domain field missing the https:// prefix in Coolify | Open the service → General → set Domain to https://... (not just ...) → Redeploy. |
| Browser shows "Your connection is not private" / certificate error | Let's Encrypt couldn't issue a cert because DNS wasn't ready when you deployed | Confirm DNS resolves correctly, then click Redeploy to retry certificate issuance. |
Build fails with exit code 137 | Compute ran out of memory during the Next.js build | Resize the Compute to ≥4 GB RAM, or temporarily resize up just for the build. |
Build fails with exit code 255 | Transient Docker BuildKit error | Click Redeploy. If it persists, run docker builder prune -f on the Compute via SSH. |
| Storefront loads but shows zero products | Database wasn't seeded after the API deployed | Re-run node src/seed.js in the API container's Terminal tab (see Step 6). |
| Storefront shows "Network error" or fails to load products | NEXT_PUBLIC_API_URL wasn't available at build time, or pointed at the wrong URL | In the frontend's Environment Variables, confirm Available at Buildtime is checked, fix the URL if needed, and Redeploy (not just restart). |
| MongoDB stuck on "Starting" status | Slow image pull on a fresh Compute | Wait 1–2 minutes. Check the Logs tab if it persists — usually no real error, just network speed. |
API returns MongoServerError: Authentication failed | MONGODB_URI is missing ?authSource=admin or has a typo in the password | Re-copy the URL from the MongoDB service in Coolify, append /shopease?authSource=admin&directConnection=true, save, redeploy. |
dpkg lock error during Coolify install | Background package updates running on a fresh Ubuntu image | Wait, then retry with the loop snippet in Step 2. |
Why does Strettch Cloud use SSH port 222 instead of the standard port 22?
Strettch Cloud uses port 222 because of a firewall restriction from its upstream internet provider that blocks the default port 22. The full explanation lives in the Strettch Cloud SSH access docs.
Do I need a domain name, or can I use the Compute's IP address directly?
Technically you can run Coolify itself on http://YOUR_COMPUTE_IP:8000, but you cannot get HTTPS without a domain, Let's Encrypt does not issue certificates for raw IPs. For a real ecommerce app, you need a domain. If you don't have one yet, registrars like Cloudflare, Porkbun, or Namecheap can sell you one for ~$10/year.
Can I use a different database, like Postgres or MySQL?
Yes. In Step 5, instead of selecting MongoDB, search for postgres or mysql and pick the version you want. You'll need to update the API code accordingly, the ShopEase backend uses Mongoose, but you could swap it for pg or mysql2 and change the connection string format.
What happens when I push to GitHub?
Coolify's GitHub App is subscribed to push events on the connected repos. When you push to main, GitHub fires a webhook to Coolify, which triggers a redeploy of the matching service. You can see this in action by editing the storefront, pushing, and watching the Deployment Logs panel light up within a few seconds.
How do I roll back a bad deployment?
Open the service in Coolify → Deployments tab → find the previous successful deployment → click Redeploy. Coolify keeps a history of recent builds so you can revert without re-pushing to git.
Can I run multiple apps on the same Compute?
Yes — that's a major reason to use Coolify in the first place. Add new services under the same project, give each one a unique subdomain, and Traefik will route traffic to the right container. RAM is your limit; once you start exceeding ~80% memory utilization, scale up the Compute or add a second one as an "app server" in Coolify's Servers section.
How do I back up MongoDB? Open the MongoDB service in Coolify → Backups tab. You can schedule automated backups to S3-compatible storage (Strettch Cloud's object storage works here, as does AWS S3, Backblaze B2, etc.). Coolify's docs cover the full configuration: see coolify.io/docs/databases/backups.
My build is slow. Can I speed it up?
Coolify caches Docker layers between builds, so subsequent deploys of the same service should be much faster than the first. If they're not, the cache may have been pruned, check disk space on the Compute (df -h). For Next.js specifically, also confirm that NEXT_TELEMETRY_DISABLED=1 is set as an environment variable to skip the telemetry check.
You have successfully deployed a full-stack ecommerce application on Strettch Cloud using Coolify. Your setup includes:
Pick one or two of these to keep building on what you've set up:
main and watch it auto-deploy.