intelidomWebsite/ADMIN_SETUP.md

3.6 KiB

Admin dashboard & gallery — self-hosted setup

The site is a SvelteKit app running on Node (adapter-node) with a local SQLite database and image files stored on disk. It's meant to run on your own server behind nginx. No third-party services.

  • Database: SQLite file at DATABASE_PATH (default ./data/app.db)
  • Uploaded images: files under UPLOADS_DIR (default ./data/uploads)
  • Auth: server-side sessions (httpOnly cookie), passwords hashed with argon2
  • Roles: admin (manage users + content) and editor (content only)

The data/ folder (database + uploads) is git-ignored — it lives only on the machine that runs the app.

Local development

npm install
npm run db:migrate        # create ./data/app.db with the tables
npm run create-admin -- --email you@example.com --password "yourpassword" --name "Ime" --role admin
npm run dev

Then open http://localhost:5173/admin, log in, and manage the gallery. The public gallery is at /gallery (also linked from the header).

Production (your home server)

1. Build

npm install
npm run build       # outputs the Node server to ./build

2. Environment variables

Variable Purpose Example
ORIGIN Required. Public URL, for correct cookies/CSRF behind nginx https://intelidom.si
PORT Port the Node app listens on 3000
BODY_SIZE_LIMIT Max upload size — the default is only 512 KB, too small for photos 52428800 (50 MB)
DATABASE_PATH SQLite file location /srv/intelidom/data/app.db
UPLOADS_DIR Uploaded images directory /srv/intelidom/data/uploads

BODY_SIZE_LIMIT matters: without raising it, uploading a normal phone photo fails with 413 Payload Too Large.

3. Initialise the database + first admin

npm run db:migrate                 # uses DATABASE_PATH
npm run create-admin -- --email you@example.com --password "strongpassword" --role admin

(Migrations also run automatically on app startup, so this is mainly to seed the first admin before the app runs. Additional users can be added the same way, or via the dashboard once Phase 2 lands.)

4. Run it

Example systemd service (/etc/systemd/system/intelidom.service):

[Service]
WorkingDirectory=/srv/intelidom
ExecStart=/usr/bin/node build
Environment=ORIGIN=https://intelidom.si
Environment=PORT=3000
Environment=BODY_SIZE_LIMIT=52428800
Environment=DATABASE_PATH=/srv/intelidom/data/app.db
Environment=UPLOADS_DIR=/srv/intelidom/data/uploads
Restart=always
User=www-data

[Install]
WantedBy=multi-user.target

sudo systemctl enable --now intelidom to start it.

5. nginx

Reverse-proxy to the Node app and let nginx serve uploaded images directly:

server {
    server_name intelidom.si;
    # ... your TLS certs ...

    client_max_body_size 50m;   # must be >= BODY_SIZE_LIMIT for uploads

    location /uploads/ {
        alias /srv/intelidom/data/uploads/;
        expires 30d;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

6. Backups

Everything worth backing up is in the data directory — back it up regularly:

cp -r /srv/intelidom/data /backups/intelidom-$(date +%F)

The previous version stored gallery images in Supabase. There's no automatic import — simply re-upload those images through the new /admin dashboard. Keep the old Supabase project until you've done so, then it can be deleted.