120 lines
3.6 KiB
Markdown
120 lines
3.6 KiB
Markdown
# 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
|
|
|
|
```sh
|
|
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
|
|
|
|
```sh
|
|
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
|
|
|
|
```sh
|
|
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`):
|
|
|
|
```ini
|
|
[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:
|
|
|
|
```nginx
|
|
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:
|
|
|
|
```sh
|
|
cp -r /srv/intelidom/data /backups/intelidom-$(date +%F)
|
|
```
|
|
|
|
## Migrating the old Supabase gallery
|
|
|
|
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.
|