
Building Your Portfolio Experience
Loading Tariqul Islam's projects...
Loading Tariqul Islam's projects...
Host your Next.js 15+ App Router project on Hostinger VPS with NGINX, Docker, and HTTPS. Secure and production-ready.
Hostinger VPS (Ubuntu 22.04+)
Domain (e.g. domain-name.com
)
GitHub repo with your Next.js project
Docker & Docker Compose installed
ssh root@your-vps-ip
sudo apt update && sudo apt upgrade -y
# Docker & Compose
curl -fsSL https://get.docker.com | bash
apt install docker-compose-plugin -y
# Git
apt install git -y
# Firewall
ufw allow OpenSSH
ufw allow 80,443/tcp
ufw enable
At your domain provider, configure A/AAAA
records:
Type | Name | Value |
---|---|---|
A | @ | VPS IPv4 |
A | www | VPS IPv4 |
AAAA | @ | VPS IPv6 |
AAAA | www | VPS IPv6 |
Note: IPv6 (AAAA
records) is optional — only add them if your VPS provider supports and assigns an IPv6 address.
Traefik will handle SSL (Let’s Encrypt) & routing for all apps.
mkdir -p /srv/apps/traefik/dynamic
cd /srv/apps/traefik
traefik.yml
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: admin@example.com
storage: /acme.json
httpChallenge:
entryPoint: web
docker-compose.yml
networks:
proxy:
external: true
services:
traefik:
image: traefik:v3.0
container_name: traefik
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./traefik.yml:/traefik.yml:ro
- ./dynamic:/dynamic
- ./acme.json:/acme.json
networks:
- proxy
Initialize
touch acme.json && chmod 600 acme.json
docker network create proxy
docker compose up -d
mkdir -p ~/srv/apps && cd ~/srv/apps
git clone git@github.com:yourusername/your-next-app.git
cd your-next-app
If private repo:
ssh-keygen -t ed25519 -C "your_email@example.com"
cat ~/.ssh/id_ed25519.pub
Add this key to GitHub > Settings > Deploy Keys.
Set environment variables:
nano .env
Dockerfile
# ---- Build stage ----
FROM node:20-alpine AS builder
WORKDIR /app
# build-time flag (default 1 to skip DB calls)
ARG SKIP_DB=1
ENV SKIP_DB=$SKIP_DB
ENV NEXT_TELEMETRY_DISABLED=1
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ---- Production runtime ----
FROM node:20-alpine
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV HOSTNAME=0.0.0.0
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next ./.next
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package*.json ./
EXPOSE 3000
CMD ["npm", "start"]
next.config.ts:
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
output: "standalone",
};
export default nextConfig;
.dockerignore:
node_modules
.next
.git
Dockerfile
docker-compose.yml
README.md
docker-compose.yml
networks:
proxy:
external: true
appnet:
external: true
services:
next-app:
build:
context: .
dockerfile: ./Dockerfile
container_name: next-app
env_file:
- ./.env
environment:
- NODE_ENV=production
- PORT=3000
- NEXT_TELEMETRY_DISABLED=1
expose:
- "3000"
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://localhost:3000/ || exit 1"]
interval: 30s
timeout: 5s
retries: 5
start_period: 20s
restart: unless-stopped
networks:
- proxy
- appnet
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
# Apex domain
- "traefik.http.routers.naturalsefa.rule=Host(`naturalsefaa.com`)"
- "traefik.http.routers.naturalsefa.entrypoints=websecure"
- "traefik.http.routers.naturalsefa.tls.certresolver=letsencrypt"
- "traefik.http.services.naturalsefa.loadbalancer.server.port=3000"
# www → apex redirect (HTTPS)
- "traefik.http.routers.naturalsefa-www.rule=Host(`www.naturalsefaa.com`)"
- "traefik.http.routers.naturalsefa-www.entrypoints=websecure"
- "traefik.http.routers.naturalsefa-www.tls.certresolver=letsencrypt"
- "traefik.http.routers.naturalsefa-www.middlewares=redirect-to-apex@docker"
- "traefik.http.middlewares.redirect-to-apex.redirectregex.regex=^https?://www\\.naturalsefaa\\.com/(.*)"
- "traefik.http.middlewares.redirect-to-apex.redirectregex.replacement=https://naturalsefaa.com/$$1"
- "traefik.http.middlewares.redirect-to-apex.redirectregex.permanent=true"
cd /srv/apps/portfolio-next
docker compose up -d --build
Now your site is live at https://example.com
🎉
cd /srv/apps/portfolio-next
git pull origin main
docker compose build
docker compose up -d
Dockerized Next.js app → portable, isolated, reproducible
Traefik reverse proxy → auto-HTTPS, multiple apps/domains handled
Clean deploy/update flow → just git pull && docker compose up -d --build