Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ apps/server/data
tray
*.log
.env
# Mounted at run time by docker-compose.yml, never baked into the image.
sakuya.config.json
run.sh
run.bat
run-hoyovault-upload.sh
Expand Down
70 changes: 0 additions & 70 deletions .env.example

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ yarn-debug.log*
yarn-error.log*
*.log
.env
# Local configuration and Docker customisation; created on first run / by you.
sakuya.config.json
docker-compose.override.yml
.vscode/*
/tmp
/out-tsc
Expand Down
19 changes: 13 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,21 @@ COPY apps/server apps/server
COPY packages/shared packages/shared
WORKDIR /app/apps/server
ENV NODE_ENV=production
# The server binds loopback by default. Inside a container that makes the published port
# unreachable, so bind all interfaces here — the container boundary is the isolation.
ENV SAKUYA_HOST=0.0.0.0
# Settings come from sakuya.config.json, mounted at /app/sakuya.config.json by docker-compose.yml.
# SAKUYA_DOCKER is what lets SAKUYA_* environment variables override it — only inside this image.
# The three pinned here are container plumbing the file can't know about:
# - host: loopback would make the published port unreachable; the container boundary is the isolation
# - port: docker/nginx.conf proxies to server:3777
# - data dir: wherever the host keeps it, it is mounted at /data
ENV SAKUYA_DOCKER=1 \
SAKUYA_HOST=0.0.0.0 \
SAKUYA_PORT=3777 \
SAKUYA_DATA_DIR=/data
EXPOSE 3777

# /api/health is registered before requireAuth in src/index.ts, so this keeps working
# with AUTH_ENABLED=true. Shell form on purpose: $PORT is expanded at run time, not build time.
# /api/health is registered before requireAuth in src/index.ts, so this keeps working with auth on.
# Shell form on purpose: $SAKUYA_PORT is expanded at run time, not build time.
HEALTHCHECK --interval=30s --timeout=5s --start-period=30s --retries=3 \
CMD bun -e "const r = await fetch('http://127.0.0.1:' + (process.env.PORT ?? 3777) + '/api/health'); process.exit(r.ok ? 0 : 1)"
CMD bun -e "const r = await fetch('http://127.0.0.1:' + (process.env.SAKUYA_PORT ?? 3777) + '/api/health'); process.exit(r.ok ? 0 : 1)"

CMD ["bun", "src/index.ts"]
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,15 @@ Open `http://localhost:5173`. No configuration required to start — everything
`apps/server/data/` by default, or in `~/.sakuya/` if that folder exists (`./setup.sh` offers to create
it, and Settings > System can move an existing library there).

To change ports, open Sakuya to your network, turn on the login or cap CPU and memory, edit
**`sakuya.config.json`** in the repository root — one file for the server, the web app and Docker,
created with the defaults on first run. [`sakuya.config.example.json`](sakuya.config.example.json)
lists every setting.

Prefer scripts? `./setup.sh` installs Bun for you if it's missing, `./run.sh` starts dev, and
`./update.sh` pulls + reinstalls. `.bat` equivalents exist for Windows.

See **[docs/SETUP.md](docs/SETUP.md)** for the full workspace layout, environment variables,
See **[docs/SETUP.md](docs/SETUP.md)** for the full workspace layout, every configuration setting,
and which folders you should never touch by hand (looking at you, `apps/server/data/`).

## API
Expand Down
12 changes: 0 additions & 12 deletions apps/server/.env.example

This file was deleted.

4 changes: 2 additions & 2 deletions apps/server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"private": true,
"type": "module",
"scripts": {
"dev": "bun --watch src/index.ts",
"start": "bun src/index.ts",
"dev": "bun src/launch.ts --watch",
"start": "bun src/launch.ts",
"typecheck": "tsc --noEmit"
},
"dependencies": {
Expand Down
13 changes: 4 additions & 9 deletions apps/server/src/auth.test.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,14 @@
import { describe, expect, test } from 'bun:test';
import crypto from 'node:crypto';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';

process.env.SAKUYA_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'sakuya-auth-'));
process.env.AUTH_ENABLED = 'true';
process.env.AUTH_SECRET = 'correct horse battery staple';
process.env.PORT = '38778';
import { useTestConfig } from './testConfig';

const SECRET = 'correct horse battery staple';
useTestConfig('auth', { port: 38778, auth: { enabled: true, secret: SECRET } });
const BASE = 'http://localhost:38778';

const { issueToken, verifyToken } = await import('./lib/auth');
await import('./index');

const SECRET = process.env.AUTH_SECRET;
const DAY = 86_400_000;

describe('session tokens', () => {
Expand Down
7 changes: 2 additions & 5 deletions apps/server/src/boards.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { expect, test } from 'bun:test';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { eq } from 'drizzle-orm';
import { useTestConfig } from './testConfig';

// Point the server at a throwaway data dir before anything opens the real database.
process.env.SAKUYA_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'sakuya-boards-'));
process.env.PORT = '38771';
useTestConfig('boards', { port: 38771 });
const BASE = 'http://localhost:38771';

const { db, sqlite, schema } = await import('./db');
Expand Down
4 changes: 2 additions & 2 deletions apps/server/src/cleanup.test.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { expect, test } from 'bun:test';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import { eq } from 'drizzle-orm';
import { useTestConfig } from './testConfig';

// Throwaway data dir before anything opens the real database. No server is started: performCleanup
// is called directly so the retention cutoff can be driven from the test.
process.env.SAKUYA_DATA_DIR = fs.mkdtempSync(path.join(os.tmpdir(), 'sakuya-cleanup-'));
useTestConfig('cleanup');

const { db, sqlite, schema } = await import('./db');
const { THUMBS_DIR } = await import('./lib/config');
Expand Down
Loading
Loading