diff --git a/README.md b/README.md index 7db24e0c..5d80ee00 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ gnubok implements double-entry bookkeeping compliant with Swedish accounting law ```bash git clone https://github.com/erp-mafia/gnubok.git cd gnubok -cp .env.docker.example .env # Fill in your Supabase credentials +./setup.sh # Prompts for Supabase credentials, generates .env docker compose up -d ``` diff --git a/SELF-HOSTING.md b/SELF-HOSTING.md index 942df900..550af1a6 100644 --- a/SELF-HOSTING.md +++ b/SELF-HOSTING.md @@ -26,7 +26,7 @@ gnubok uses passwordless magic link login — the default Supabase email auth se ## 3. Apply Database Migrations -The `supabase/migrations/` directory contains 52 ordered SQL files that set up the full schema, including tables, RLS policies, triggers, and functions. +The `supabase/migrations/` directory contains 63 ordered SQL files that set up the full schema, including tables, RLS policies, triggers, and functions. **Option A — Supabase CLI (recommended):** @@ -43,7 +43,7 @@ supabase db push **Option B — SQL Editor:** -Run each file in `supabase/migrations/` in order (001 through 052) in the Supabase SQL Editor. They must be applied sequentially — later migrations depend on earlier ones. +Run each file in `supabase/migrations/` in order in the Supabase SQL Editor. They must be applied sequentially — later migrations depend on earlier ones. ### PostgreSQL Extensions @@ -60,6 +60,18 @@ These are all available on Supabase hosted. `pg_cron` requires a paid plan — i ## 4. Configure Environment +**Option A — Setup script (recommended):** + +```bash +git clone https://github.com/erp-mafia/gnubok.git +cd gnubok +./setup.sh +``` + +The script checks prerequisites, prompts for your Supabase credentials, auto-generates `CRON_SECRET`, and writes everything to `.env`. + +**Option B — Manual:** + ```bash git clone https://github.com/erp-mafia/gnubok.git cd gnubok @@ -89,7 +101,7 @@ This starts two containers: | Container | Purpose | |-----------|---------| -| `app` | Next.js application (pulls `ghcr.io/erp-mafia/gnubok:latest`) | +| `app` | Next.js application (`ghcr.io/erp-mafia/gnubok:latest`) | | `cron` | Scheduled jobs via [supercronic](https://github.com/aptible/supercronic) | The cron container waits for the app health check to pass before starting. diff --git a/docker-compose.yml b/docker-compose.yml index 6b54c04c..a5e5f8a5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: app: - image: ghcr.io/erp-mafia/erp-base:latest + image: ghcr.io/erp-mafia/gnubok:latest env_file: .env ports: - "${PORT:-3000}:3000" diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh index 75cf7a58..a6014d7b 100755 --- a/docker-entrypoint.sh +++ b/docker-entrypoint.sh @@ -1,6 +1,32 @@ #!/bin/sh set -e +# ─── Validate required environment variables ─── +missing="" +for var in NEXT_PUBLIC_SUPABASE_URL NEXT_PUBLIC_SUPABASE_ANON_KEY SUPABASE_SERVICE_ROLE_KEY NEXT_PUBLIC_APP_URL CRON_SECRET; do + eval val=\$$var + if [ -z "$val" ]; then + missing="$missing - $var\n" + fi +done + +if [ -n "$missing" ]; then + printf "ERROR: Missing required environment variables:\n%b\nSee .env.docker.example for reference.\n" "$missing" >&2 + exit 1 +fi + +# Warn if placeholder values are still set +placeholders_found="" +case "$NEXT_PUBLIC_SUPABASE_ANON_KEY" in *your-anon-key*) placeholders_found="$placeholders_found - NEXT_PUBLIC_SUPABASE_ANON_KEY\n" ;; esac +case "$SUPABASE_SERVICE_ROLE_KEY" in *your-service-role-key*) placeholders_found="$placeholders_found - SUPABASE_SERVICE_ROLE_KEY\n" ;; esac +case "$NEXT_PUBLIC_SUPABASE_URL" in *your-project*) placeholders_found="$placeholders_found - NEXT_PUBLIC_SUPABASE_URL\n" ;; esac +case "$NEXT_PUBLIC_APP_URL" in *your-domain*) placeholders_found="$placeholders_found - NEXT_PUBLIC_APP_URL\n" ;; esac +case "$CRON_SECRET" in *generate-a-random-secret*) placeholders_found="$placeholders_found - CRON_SECRET\n" ;; esac + +if [ -n "$placeholders_found" ]; then + printf "WARNING: These variables appear to contain placeholder values:\n%bPlease set them to real values before running in production.\n" "$placeholders_found" >&2 +fi + # Replace build-time placeholder sentinels with runtime env vars in static JS bundles. # This allows a single pre-built image to work with any Supabase project. if [ -d /app/.next/static ]; then diff --git a/setup.sh b/setup.sh new file mode 100755 index 00000000..cb3ab248 --- /dev/null +++ b/setup.sh @@ -0,0 +1,81 @@ +#!/bin/sh +set -e + +echo "gnubok setup" +echo "============" +echo "" + +# ─── Check prerequisites ─── +ok=true +if ! command -v docker >/dev/null 2>&1; then + echo "ERROR: docker is not installed. Install it from https://docs.docker.com/get-docker/" + ok=false +fi +if ! docker compose version >/dev/null 2>&1; then + echo "ERROR: docker compose is not available. Install Docker Compose v2+." + ok=false +fi +if [ "$ok" = false ]; then + exit 1 +fi + +# ─── Create .env file ─── +if [ -f .env ]; then + printf ".env already exists. Overwrite? [y/N] " + read -r answer + case "$answer" in + [yY]*) ;; + *) echo "Keeping existing .env. Exiting."; exit 0 ;; + esac +fi + +if [ ! -f .env.docker.example ]; then + echo "ERROR: .env.docker.example not found. Are you in the gnubok directory?" + exit 1 +fi + +cp .env.docker.example .env + +# ─── Auto-generate CRON_SECRET ─── +if command -v openssl >/dev/null 2>&1; then + cron_secret=$(openssl rand -hex 32) +else + cron_secret=$(head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n') +fi +sed -i.bak "s|generate-a-random-secret|${cron_secret}|" .env && rm -f .env.bak + +# ─── Prompt for Supabase values ─── +echo "" +echo "Enter your Supabase project values (from Settings > API in the Supabase dashboard):" +echo "" + +printf "NEXT_PUBLIC_SUPABASE_URL (e.g. https://abcdefgh.supabase.co): " +read -r supabase_url +if [ -n "$supabase_url" ]; then + sed -i.bak "s|https://your-project.supabase.co|${supabase_url}|" .env && rm -f .env.bak +fi + +printf "NEXT_PUBLIC_SUPABASE_ANON_KEY: " +read -r anon_key +if [ -n "$anon_key" ]; then + sed -i.bak "s|your-anon-key|${anon_key}|" .env && rm -f .env.bak +fi + +printf "SUPABASE_SERVICE_ROLE_KEY: " +read -r service_key +if [ -n "$service_key" ]; then + sed -i.bak "s|your-service-role-key|${service_key}|" .env && rm -f .env.bak +fi + +printf "NEXT_PUBLIC_APP_URL [http://localhost:3000]: " +read -r app_url +app_url="${app_url:-http://localhost:3000}" +sed -i.bak "s|https://your-domain.com|${app_url}|" .env && rm -f .env.bak + +echo "" +echo "Done! .env has been configured." +echo "" +echo "Next steps:" +echo " 1. Apply database migrations (see SELF-HOSTING.md section 3)" +echo " 2. Run: docker compose up -d" +echo ""