docs(project): add README with reverse-proxy and quick-start guide
Root README covering the stack, quick start, and dev commands, plus a Reverse proxy (nginx) section: client_max_body_size for large uploads, forwarded headers feeding the rate limiter, and buffering-off for streaming large media. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,98 @@
|
|||||||
|
# Tanabata File Manager
|
||||||
|
|
||||||
|
A multi-user, tag-based web file manager for images and video. Go + Gin backend
|
||||||
|
(Clean Architecture, pgx, goose migrations), SvelteKit SPA frontend, PostgreSQL,
|
||||||
|
JWT auth — shipped as a single Docker image that serves both the API and the
|
||||||
|
built SPA on one port.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [`openapi.yaml`](openapi.yaml) — full REST API specification
|
||||||
|
- [`docs/DEPLOY.md`](docs/DEPLOY.md) — production deploy (Gitea Actions → host)
|
||||||
|
- [`docs/GO_PROJECT_STRUCTURE.md`](docs/GO_PROJECT_STRUCTURE.md) — backend architecture
|
||||||
|
- [`docs/FRONTEND_STRUCTURE.md`](docs/FRONTEND_STRUCTURE.md) — frontend architecture
|
||||||
|
- [`.env.example`](.env.example) — every configuration variable, documented
|
||||||
|
|
||||||
|
## Quick start
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp .env.example .env # then edit the secrets (JWT_SECRET, ADMIN_PASSWORD, …)
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
By default this runs the app plus a bundled PostgreSQL container
|
||||||
|
(`COMPOSE_PROFILES=with-db`). To point at a Postgres already on the host, set
|
||||||
|
`COMPOSE_PROFILES=` empty and aim `DATABASE_URL` at `host.docker.internal`. See
|
||||||
|
[`.env.example`](.env.example) for the full matrix.
|
||||||
|
|
||||||
|
The app is published on **127.0.0.1** only and expects a reverse proxy in front
|
||||||
|
(see below). The default port is **42776** — the sum of the Unicode code points
|
||||||
|
of 七夕.
|
||||||
|
|
||||||
|
## Reverse proxy (nginx)
|
||||||
|
|
||||||
|
The container publishes its port on loopback (`127.0.0.1:${APP_PORT}:42776` in
|
||||||
|
[`docker-compose.yml`](docker-compose.yml)), so a reverse proxy on the host
|
||||||
|
terminates TLS and forwards to it. Three settings matter for this app:
|
||||||
|
|
||||||
|
1. **`client_max_body_size`** — uploads go up to `MAX_UPLOAD_BYTES` (500 MiB by
|
||||||
|
default). nginx caps request bodies at **1 MiB** out of the box, so without
|
||||||
|
this every large upload fails with `413`.
|
||||||
|
2. **Forwarded headers** — the app trusts `X-Forwarded-For` only from the hops in
|
||||||
|
`TRUSTED_PROXIES` (default: loopback + Docker bridge ranges) and keys its
|
||||||
|
login/refresh rate limiter on the resulting client IP. If the proxy doesn't
|
||||||
|
send the header, every request looks like it comes from the proxy and shares
|
||||||
|
one rate-limit bucket.
|
||||||
|
3. **Streaming for big media** — turning request/response buffering off lets
|
||||||
|
large uploads stream straight to the app and lets video range-seeks work
|
||||||
|
without nginx spooling whole files to disk first.
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name tanabata.example.com;
|
||||||
|
|
||||||
|
# ssl_certificate / ssl_certificate_key ... (e.g. from certbot)
|
||||||
|
|
||||||
|
# Match MAX_UPLOAD_BYTES (500 MiB default); nginx defaults to 1m → 413.
|
||||||
|
client_max_body_size 512m;
|
||||||
|
|
||||||
|
location / {
|
||||||
|
proxy_pass http://127.0.0.1:42776; # APP_PORT
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
|
# Stream large uploads/downloads instead of buffering to disk; keeps
|
||||||
|
# video range-seek responsive. Scope these to file/preview locations
|
||||||
|
# instead if you'd rather keep buffering for small JSON responses.
|
||||||
|
proxy_request_buffering off;
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you run the app **without** a proxy and want it reachable on the LAN, drop the
|
||||||
|
`127.0.0.1:` prefix from the `ports` line in
|
||||||
|
[`docker-compose.yml`](docker-compose.yml) and adjust `TRUSTED_PROXIES`
|
||||||
|
accordingly.
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Backend
|
||||||
|
cd backend
|
||||||
|
go run ./cmd/server # dev server
|
||||||
|
go test ./... # all tests
|
||||||
|
|
||||||
|
# Frontend
|
||||||
|
cd frontend
|
||||||
|
npm run dev # Vite dev server
|
||||||
|
npm run build # production build
|
||||||
|
npm run generate:types # regenerate API types from openapi.yaml
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user