DevOps & Deployment

Zero to Production: Deploying Next.js, Docker, and Caddy with LovieMe Subdomains

October 09, 2026 • 8 minutes
Sagar Kewat
Sagar KewatFounder & Lead Engineer
Zero to Production: Deploying Next.js, Docker, and Caddy with LovieMe Subdomains

Take full ownership of your deployment stack. Here is how to configure a production Linux VPS with Next.js, Docker, automated TLS via Caddy, and a clean LovieMe custom subdomain.

While platform-as-a-service providers like Vercel and Railway are great, running your own Virtual Private Server (VPS) gives you total architectural control, lower compute costs, and zero vendor lock-in.

In this guide, we will connect a LovieMe subdomain (app.lovie.me) to a clean Ubuntu server with automated HTTPS and Docker containerization.


📋 Architecture Overview

Our production stack consists of:

  • DNS: LovieMe A Record → Public VPS IPv4
  • Reverse Proxy: Caddy 2 (Automatic Let's Encrypt TLS 1.3 issuance)
  • Application: Next.js 16 Docker container (listening on internal port 3000)
  • Orchestration: Docker Compose with automated restart policies

🛠️ Step 1: Configure LovieMe DNS

  1. In your LovieMe console, claim your prefix (e.g. app).
  2. Add an A Record:
    • Type: A
    • Name: @
    • Content: <Your-VPS-Public-IP> (e.g. 198.51.100.42)
    • TTL: 300

Verify resolution with:

dig +short A app.lovie.me

🐳 Step 2: Dockerize Your Next.js Application

Create a multi-stage Dockerfile inside your Next.js project root:

FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=3000
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
EXPOSE 3000
CMD ["node", "server.js"]

⚙️ Step 3: Define Docker Compose

Create a docker-compose.yml file that connects your container to Caddy:

version: "3.8"

services:
  web:
    build: .
    restart: always
    environment:
      - NODE_ENV=production
    networks:
      - internal_net

  caddy:
    image: caddy:2-alpine
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - internal_net
    depends_on:
      - web

networks:
  internal_net:

volumes:
  caddy_data:
  caddy_config:

🔒 Step 4: Configure the Caddyfile

Caddy automatically requests, verifies, and renews Let's Encrypt or ZeroSSL certificates over ACME. Create a Caddyfile:

app.lovie.me {
    reverse_proxy web:3000

    encode gzip zstd

    header {
        Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
        X-Content-Type-Options "nosniff"
        X-Frame-Options "DENY"
        Referrer-Policy "strict-origin-when-cross-origin"
    }
}

🚀 Step 5: Launch to Production

On your VPS terminal, launch your containers in detached mode:

docker compose up -d --build

Inspect Caddy's logs to witness automatic certificate issuance:

docker compose logs -f caddy

You will see:

certificate obtained successfully {"identifier": "app.lovie.me", "issuer": "acme-v02.api.letsencrypt.org-directory"}

Open https://app.lovie.me in your browser: you now have a fully containerized, high-performance production Next.js application running with a clean LovieMe custom domain and automated TLS encryption!