Add NK Admin web container on 127.0.0.1:18080 with placeholder page

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
metatroncubeswdev 2026-10-30 10:51:14 -04:00
parent 7b4239544c
commit d368880601
6 changed files with 77 additions and 4 deletions

View File

@ -11,6 +11,17 @@ Self-hosted [Supabase](https://supabase.com/docs/guides/self-hosting/docker) in
| Studio | Admin dashboard in the browser (password protected) | | Studio | Admin dashboard in the browser (password protected) |
| Caddy | HTTPS with automatic Let's Encrypt certificates | | Caddy | HTTPS with automatic Let's Encrypt certificates |
## Ports and reverse proxy (live server)
Everything runs in **one** Docker Compose project (`~/APPS/nk-backend/supabase-project`). Only two ports are opened, and only on `127.0.0.1`; HestiaCP's nginx handles HTTPS and forwards to them:
| Domain | Hestia reverse proxy to | What it is |
|---|---|---|
| `app.nkbmusic.com` | `http://127.0.0.1:18000` | API for the app + Supabase Studio |
| `admin.nkbmusic.com` | `http://127.0.0.1:18080` | NK Admin website (container `nk-admin`) |
Internal only (never proxied): Postgres `127.0.0.1:15432`, pooler `127.0.0.1:16543`. Change ports with `API_GW_HTTP_PORT`, `NK_ADMIN_PORT`, `NK_DB_PORT`, `NK_POOLER_PORT` in the project's `.env`.
## Updating the live server ## Updating the live server
The code lives at https://git.metatroncube.in/MetatroncubeSoftwareSolutions/nkbmusic and the server runs from a clone of it in `~/APPS/nanga_kathai`. After pushing changes: The code lives at https://git.metatroncube.in/MetatroncubeSoftwareSolutions/nkbmusic and the server runs from a clone of it in `~/APPS/nanga_kathai`. After pushing changes:

View File

@ -0,0 +1,24 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="robots" content="noindex">
<title>NK Admin</title>
<style>
:root { color-scheme: dark; }
body { margin: 0; min-height: 100vh; display: grid; place-items: center; background: #0B1A14;
color: #FBF7EE; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; }
main { text-align: center; padding: 24px; }
h1 { margin: 0 0 8px; font-size: 28px; }
p { margin: 0; color: #9FB3A6; }
.dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; background: #F5B335; margin-right: 8px; }
</style>
</head>
<body>
<main>
<h1><span class="dot"></span>Nanga Kathai Admin</h1>
<p>The dashboard is being built. This page confirms the server is set up.</p>
</main>
</body>
</html>

View File

@ -88,11 +88,17 @@ if [ ! -f "$PROJECT/.env" ]; then
sh "$HERE/install.sh" "$DOMAIN" "$NK_DIR" sh "$HERE/install.sh" "$DOMAIN" "$NK_DIR"
else else
say "Existing install found: refreshing the NK config" say "Existing install found: refreshing the NK config"
cp -r "$HERE/caddy" "$HERE/email-templates" "$HERE/sql" "$PROJECT/nk/" cp -r "$HERE/caddy" "$HERE/email-templates" "$HERE/sql" "$HERE/nginx" "$PROJECT/nk/"
cp "$HERE/docker-compose.nk.yml" "$HERE/docker-compose.nk-caddy.yml" "$PROJECT/" cp "$HERE/docker-compose.nk.yml" "$HERE/docker-compose.nk-caddy.yml" "$PROJECT/"
fi fi
cd "$PROJECT" cd "$PROJECT"
# Admin website: the placeholder until a real build has been published (deploy-admin.sh).
if [ ! -f nk/admin/index.html ]; then
mkdir -p nk/admin
cp "$HERE/admin-placeholder/index.html" nk/admin/
fi
env_get() { grep -E "^$1=" .env | head -n1 | cut -d= -f2-; } env_get() { grep -E "^$1=" .env | head -n1 | cut -d= -f2-; }
env_set() { # safe for any characters in the value env_set() { # safe for any characters in the value
K="$1" V="$2" awk 'BEGIN { k = ENVIRON["K"]; v = ENVIRON["V"]; done = 0 } K="$1" V="$2" awk 'BEGIN { k = ENVIRON["K"]; v = ENVIRON["V"]; done = 0 }
@ -171,8 +177,9 @@ CRON="30 2 * * * sh $HERE/backup.sh $PROJECT $BACKUPS >> $BACKUPS/backup.log 2>&
# --- Done -------------------------------------------------------------------- # --- Done --------------------------------------------------------------------
PROXY_NOTE="" PROXY_NOTE=""
[ "$NK_PROXY" = caddy ] || PROXY_NOTE=" [ "$NK_PROXY" = caddy ] || PROXY_NOTE="
Reverse proxy: point https://$DOMAIN at http://127.0.0.1:$API_GW_HTTP_PORT Reverse proxy (HestiaCP: Web > domain > Proxy, or a custom nginx proxy template):
(HestiaCP: Web > $DOMAIN > Proxy, or a custom nginx proxy template) https://$DOMAIN -> http://127.0.0.1:$API_GW_HTTP_PORT (API + Studio)
https://admin.${DOMAIN#*.} -> http://127.0.0.1:${NK_ADMIN_PORT:-18080} (NK Admin)
" "
cat <<EOF cat <<EOF

View File

@ -17,6 +17,18 @@ services:
volumes: volumes:
- ./nk/email-templates:/usr/share/nginx/html:ro - ./nk/email-templates:/usr/share/nginx/html:ro
# NK Admin website (static files). The server's web server proxies
# https://admin.<domain> to 127.0.0.1:${NK_ADMIN_PORT}. It talks to the API above;
# only admin accounts can change anything (enforced by the database).
nk-admin:
image: nginx:1.27-alpine
restart: unless-stopped
ports:
- 127.0.0.1:${NK_ADMIN_PORT:-18080}:80
volumes:
- ./nk/admin:/usr/share/nginx/html:ro
- ./nk/nginx/admin.conf:/etc/nginx/conf.d/default.conf:ro
# Send a 6-digit code (not a link) for passwordless email sign-in. # Send a 6-digit code (not a link) for passwordless email sign-in.
auth: auth:
depends_on: depends_on:

View File

@ -68,7 +68,7 @@ set_env DASHBOARD_PASSWORD "$(LC_ALL=C tr -dc 'A-Za-z0-9' </dev/urandom | head -
echo "==> Adding Nanga Kathai config" echo "==> Adding Nanga Kathai config"
mkdir -p nk mkdir -p nk
cp -r "$HERE/caddy" "$HERE/email-templates" "$HERE/sql" nk/ cp -r "$HERE/caddy" "$HERE/email-templates" "$HERE/sql" "$HERE/nginx" nk/
cp "$HERE/docker-compose.nk.yml" "$HERE/docker-compose.nk-caddy.yml" . cp "$HERE/docker-compose.nk.yml" "$HERE/docker-compose.nk-caddy.yml" .
mkdir -p nk/migrations mkdir -p nk/migrations
cp "$HERE/../supabase/migrations/"*.sql nk/migrations/ cp "$HERE/../supabase/migrations/"*.sql nk/migrations/

19
server/nginx/admin.conf Normal file
View File

@ -0,0 +1,19 @@
# NK Admin: a single-page web app. Unknown paths load index.html so deep links work.
server {
listen 80;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
}
# Built files have content hashes or change rarely; cache them.
location ~* \.(js|wasm|css|png|jpg|svg|ttf|otf|woff2?)$ {
expires 7d;
}
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header Referrer-Policy same-origin always;
}