Files
2026-09-28 23:15:47 +05:30

2.1 KiB

Deploy 100kmph web on Debian 12

Apache and MariaDB are already on the box. Add Node.js 20 LTS. The Next process listens on 127.0.0.1:3000 only. Apache is the public front. Do not open port 3000.

MariaDB

  1. Edit the password in mariadb-grants.sql.
  2. Apply it as an admin: mariadb < mariadb-grants.sql
  3. Apply ../db/001_init.sql as an admin, not as hundredkmph.
  4. Do not enable remote root.

The app user gets SELECT, INSERT, and UPDATE on hundredkmph from localhost only.

App process

Build on the server (or copy a build from a machine with the same Node major version):

cd /opt/hundredkmph/src/web
npm ci
npm run build
mkdir -p /opt/hundredkmph/web
rm -rf /opt/hundredkmph/web/*
cp -a .next/standalone/. /opt/hundredkmph/web/
mkdir -p /opt/hundredkmph/web/.next
cp -a .next/static /opt/hundredkmph/web/.next/static

Create a system user and a root-only env file:

useradd --system --home /opt/hundredkmph/web --shell /usr/sbin/nologin hundredkmph
install -d -m 0750 -o root -g root /etc/hundredkmph
install -m 0600 -o root -g root /dev/null /etc/hundredkmph/web.env

/etc/hundredkmph/web.env contains only:

DATABASE_URL=mysql://hundredkmph:THE_PASSWORD@127.0.0.1:3306/hundredkmph
SYNC_TOKEN=a-long-random-secret

systemd reads that file as root before dropping to hundredkmph. HOSTNAME=127.0.0.1 and PORT=3000 are set in hundredkmph-web.service, so the process does not listen on a public interface.

cp hundredkmph-web.service /etc/systemd/system/hundredkmph-web.service
systemctl daemon-reload
systemctl enable --now hundredkmph-web

npm start is the non-standalone equivalent: next start -H 127.0.0.1 -p 3000.

Apache

Leave the existing TLS virtual host in place. Enable proxy and proxy_http, then include apache-hundredkmph.conf inside that virtual host. WebSocket upgrade is not required.

mod_proxy appends the client address to X-Forwarded-For. The status lookup uses the last address in that header.