INFRASTRUCTURE2026-04-09📖 2 min read

Self-Hosting a Next.js Browser Game on Coolify: A Production Setup Walkthrough

Self-Hosting a Next.js Browser Game on Coolify: A Production Setup Walkthrough

A hands-on walkthrough of self-hosting a Next.js browser mahjong game "Janten" on a VPS via Coolify — Nixpacks build, separate production/preview environments, GitHub Actions CI/CD, memory tuning, and Let's Encrypt SSL configuration.

髙木 晃宏

代表 / エンジニア

👨‍💼

At aduce, we develop a browser mahjong game called Janten (janten.net) in Next.js and self-host it on Coolify atop a VPS. This article walks through the production setup, with the actual configuration files.

What Is Coolify? A Choice for Self-Hosting Next.js on a VPS

Coolify is an open-source PaaS (Platform as a Service) that delivers a Vercel/Netlify-style deployment experience on your own VPS. It integrates with GitHub repositories and triggers builds and deploys on push.

We chose Coolify for self-hosting Next.js for a simple reason: it bundles automated SSL certificate management, health checks, and resource limits in a single VPS. We can operate a long-session app like a game without worrying about Vercel's usage-based billing.

The janten.net Infrastructure (Production + Preview)

Janten runs two Coolify environments: production and preview. Production tracks the prod branch, preview tracks main, each registered as a separate application in Coolify.

EnvironmentDomainBranchPurpose
Productionjanten.netprodPublic-facing
Previewpre.janten.netmainDev verification

The preview environment has an IP allowlist so only authorized users can access it.

# IP restriction on the preview environment ip_allow: - 14.11.163.0/32

Zero-Configuration Builds with Nixpacks

Coolify natively supports Nixpacks as a build pack. When it detects a package.json, it automatically sets up a Node.js environment and runs the build command.

Janten needs to pre-build a local package, mahjong-core, so we handle that in the package.json build script:

{ "scripts": { "build": "cd mahjong-core && npm install && npm run build && cd .. && next build", "start": "next start" } }

Coolify's configuration is simple:

build: pack: nixpacks command: npm run build runtime: start_command: npm run start port: 3000

No need to maintain a custom Dockerfile. Just define build and start in package.json and the Next.js app deploys.

CI/CD Integration with GitHub Actions

Separate from Coolify's GitHub integration, we run CI (tests and build verification) via GitHub Actions. The pipeline below runs on pushes and PRs to the main and prod branches.

name: CI on: push: branches: [main, prod] pull_request: branches: [main, prod] jobs: ci: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 22 cache: npm - run: npm ci - name: Build mahjong-core run: cd mahjong-core && npm install && npm run build - name: Test run: npm test - name: Build run: npx next build

Only commits that pass CI are merged to main, and merging main into prod triggers the production deploy. Coolify's webhook detects the push event and kicks off build and deploy automatically.

Production Tuning (Memory Limits, Health Checks)

VPS resources are finite, so we set memory and CPU caps on the container.

environment: runtime: NODE_ENV: production NODE_OPTIONS: "--max-old-space-size=768" resources: memory: 512 cpu: 500 healthcheck: path: / interval: 30 timeout: 10 retries: 3

The key here is NODE_OPTIONS with --max-old-space-size=768. Even though the container's memory cap is 512MB, setting Node.js's heap limit slightly higher prevents out-of-memory errors during build while still letting the OOM Killer step in to restart a runaway container — that's the design.

Health checks hit / every 30 seconds and restart the container after 3 consecutive failures. Browser games rely on long-running sessions, so automatic recovery on anomalies is critical.

Automatic SSL with Let's Encrypt

Coolify has built-in Let's Encrypt integration — just set the domain and SSL certs are obtained and renewed automatically.

domains: primary: janten.net ssl: enabled: true auto_renew: true

That's the entire configuration. No manual certificate renewals, no cron jobs. Under the hood, Coolify runs Traefik as a reverse proxy, handling HTTPS termination and Let's Encrypt challenge responses. The same settings apply uniformly to both production and preview environments.

Summary

Running Coolify on a VPS lets us deploy a Next.js browser game like Janten without a Dockerfile, while unifying SSL, health checks, and resource management. Zero-config builds via Nixpacks, CI/CD combined with GitHub Actions, an IP-restricted preview environment — small teams can still maintain production-quality infrastructure.

At aduce we offer technical advisory based on this kind of infrastructure and DevOps experience. If you need help with VPS self-hosting or CI/CD pipeline setup, please reach out via Contact.