docs: rebrand README + add Docker and bare-metal deploy

- Rewrite README with RetroBlog branding, config table, and two deploy
  paths (Docker Compose + bare-metal/systemd).
- Enable Next.js standalone output for slim runtime images.
- Add multi-stage Dockerfile (builds better-sqlite3 natively, runs as
  non-root, persists /app/data), docker-compose.yml, and .dockerignore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 03:57:35 +02:00
parent 307e0b48da
commit 2f373e683b
5 changed files with 227 additions and 34 deletions
+15
View File
@@ -0,0 +1,15 @@
node_modules
.next
.git
.gitignore
data
*.tsbuildinfo
next-env.d.ts
.env*
README.md
Dockerfile
.dockerignore
docker-compose.yml
npm-debug.log*
.pnpm-debug.log*
.DS_Store
+45
View File
@@ -0,0 +1,45 @@
# syntax=docker/dockerfile:1
# ---- deps: install node_modules (native build tools for better-sqlite3) ----
FROM node:22-bookworm-slim AS deps
WORKDIR /app
RUN apt-get update && apt-get install -y --no-install-recommends \
python3 make g++ \
&& rm -rf /var/lib/apt/lists/*
RUN corepack enable
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile
# ---- builder: compile the Next.js standalone server ----
FROM node:22-bookworm-slim AS builder
WORKDIR /app
RUN corepack enable
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN pnpm build
# ---- runner: minimal runtime image ----
FROM node:22-bookworm-slim AS runner
WORKDIR /app
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
PORT=3000 \
HOSTNAME=0.0.0.0
# Non-root user; owns the data volume so SQLite can write.
RUN addgroup --system --gid 1001 nodejs \
&& adduser --system --uid 1001 nextjs
# Standalone output bundles the traced node_modules (incl. the better-sqlite3
# native binary), so no install/rebuild is needed here.
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
RUN mkdir -p /app/data && chown -R nextjs:nodejs /app/data
VOLUME ["/app/data"]
USER nextjs
EXPOSE 3000
CMD ["node", "server.js"]
+146 -33
View File
@@ -1,50 +1,163 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). <div align="center">
## Getting Started # 🕹️ RetroBlog
First, run the development server: **A self-hosted blog engine with swappable OS / game-console skins.**
Write Markdown posts, flip between retro themes (Windows, PS1, PS2, PS3, Wii,
NDS, Dreamcast, JV2002…), and run the whole thing from a single SQLite file.
</div>
---
## Features
- **Markdown posts** — create / edit / delete with slugs, tags, excerpts, dates.
- **Swappable skins** — pick the default theme; optionally let visitors switch.
- **Admin panel** — single-password login, signed session cookie.
- **Import / export** — JSON backup of settings and posts.
- **Zero external services** — data lives in one SQLite file (`data/blog.db`).
Stack: Next.js 16 (App Router) · React 19 · better-sqlite3 · marked.
---
## Quick start (development)
```bash ```bash
npm run dev pnpm install
# or
yarn dev
# or
pnpm dev pnpm dev
# or
bun dev
``` ```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. Open <http://localhost:3000>. Admin panel at <http://localhost:3000/admin>
(default password `admin` in dev).
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. ---
## Configuration
All config is environment variables. Copy `.env.example` to `.env` and edit.
| Variable | Required | Default | Purpose |
| ---------------------- | -------- | ---------------- | --------------------------------------------------------- |
| `ADMIN_PASSWORD` | **prod** | `admin` | Password for `/admin`. **Set this in production.** |
| `ADMIN_SESSION_SECRET` | **prod** | `ADMIN_PASSWORD` | Signs the admin session cookie. Use a long random string. |
| `PORT` | no | `3000` | Port the server listens on. |
Generate a secret:
```bash
openssl rand -hex 32
```
**Data** is stored in `./data/blog.db` (created automatically). Back up that
directory to back up the whole site.
---
## Deploy — Docker (recommended)
Needs Docker + the Compose plugin.
```bash
# 1. Set production secrets
cp .env.example .env
$EDITOR .env # set ADMIN_PASSWORD and ADMIN_SESSION_SECRET
# 2. Build and run
docker compose up -d --build
```
Site is live on <http://localhost:3000>. The database persists in the
`retroblog-data` Docker volume across rebuilds.
Common operations:
```bash
docker compose logs -f # tail logs
docker compose down # stop (keeps the data volume)
docker compose up -d --build # update after pulling new code
```
**Back up the database:**
```bash
docker compose exec retroblog sh -c 'cat /app/data/blog.db' > backup-$(date +%F).db
```
> Put a TLS-terminating reverse proxy (Caddy, nginx, Traefik) in front for
> HTTPS in production. RetroBlog speaks plain HTTP on `PORT`.
---
## Deploy — bare metal
Needs Node.js 22+ and `pnpm` (`corepack enable`). A C toolchain
(`build-essential`, `python3`) is required once, to compile better-sqlite3.
```bash
# 1. Install deps and build
pnpm install --frozen-lockfile
pnpm build
# 2. Set production secrets
export ADMIN_PASSWORD='your-strong-password'
export ADMIN_SESSION_SECRET="$(openssl rand -hex 32)"
# 3. Start
pnpm start # serves on PORT (default 3000)
```
### Run it as a service (systemd)
`/etc/systemd/system/retroblog.service`:
```ini
[Unit]
Description=RetroBlog
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/retroblog
ExecStart=/usr/bin/pnpm start
Restart=on-failure
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=ADMIN_PASSWORD=your-strong-password
Environment=ADMIN_SESSION_SECRET=your-long-random-secret
User=www-data
Group=www-data
[Install]
WantedBy=multi-user.target
```
```bash
sudo systemctl daemon-reload
sudo systemctl enable --now retroblog
```
The SQLite database lives in `WorkingDirectory/data/blog.db` — make sure the
service `User` can write there, and back up that file.
---
## Admin panel ## Admin panel
Visit [http://localhost:3000/admin](http://localhost:3000/admin) and sign in with Sign in at `/admin` with `ADMIN_PASSWORD`. From there:
`ADMIN_PASSWORD` (see `.env.example`; defaults to `admin` in dev). From there you can:
- **Posts** — full create / edit / delete with Markdown bodies, slugs, tags, and dates. - **Posts** — full create / edit / delete with Markdown bodies, slugs, tags, dates.
- **Settings** — branding (title, subtitle, footer, version), the default theme for - **Settings** — branding (title, subtitle, footer, version), default theme for
new visitors, whether the public theme switcher is shown, and which skins it offers. new visitors, whether the public theme switcher is shown, and which skins it offers.
- **Import / export** — download a JSON backup of settings and/or posts, and import - **Import / export** — download a JSON backup of settings and/or posts, and
one back (posts can replace or append). import one back (posts can replace or append).
Auth is a single password kept in `ADMIN_PASSWORD`, with a signed session cookie All `/admin/*` routes are gated by middleware behind the signed session cookie.
(`ADMIN_SESSION_SECRET`). All `/admin/*` routes are gated by middleware.
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. ---
## Learn More ## License
To learn more about Next.js, take a look at the following resources: See repository.
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+18
View File
@@ -0,0 +1,18 @@
services:
retroblog:
build: .
image: retroblog:latest
container_name: retroblog
restart: unless-stopped
ports:
- "3000:3000"
environment:
# CHANGE THESE before exposing to the internet.
ADMIN_PASSWORD: ${ADMIN_PASSWORD:-admin}
ADMIN_SESSION_SECRET: ${ADMIN_SESSION_SECRET:-change-me-to-a-long-random-string}
volumes:
# Persist the SQLite database across container rebuilds.
- retroblog-data:/app/data
volumes:
retroblog-data:
+3 -1
View File
@@ -1,7 +1,9 @@
import type { NextConfig } from "next"; import type { NextConfig } from "next";
const nextConfig: NextConfig = { const nextConfig: NextConfig = {
/* config options here */ // Emit a self-contained server in .next/standalone for slim Docker images
// and simple bare-metal deploys.
output: "standalone",
}; };
export default nextConfig; export default nextConfig;