From bcef2d7b52601f41194762d6beb667efe8fb62b5 Mon Sep 17 00:00:00 2001 From: delete Date: Wed, 10 Jun 2026 21:26:37 +0300 Subject: [PATCH] add readme --- README.md | 255 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..9b45847 --- /dev/null +++ b/README.md @@ -0,0 +1,255 @@ +# Update Server + +Self-hosted server for publishing application updates. An administrator uploads +versioned release artifacts through a web UI, and client applications discover +and download allowed updates through a bearer-authenticated HTTP API. + +The project is designed for small private deployments: one Go application, one +SQLite database, local artifact storage, and HTTPS termination by a reverse +proxy such as Caddy or Nginx. + +## What It Does + +- Admin web UI at `/admin`. +- Project and tag management. +- Release artifact upload per project. +- Client API key management with project or tag scope rules. +- Client API at `/api/v1`. +- Private artifact downloads through the application, not through a public file + directory. +- SQLite migrations applied automatically on startup. +- Docker image and Docker Compose deployment files. + +## Current Readiness + +This is a usable MVP. It is ready to run locally or on a small server with +Docker, create an admin user, create projects, upload releases, issue API keys, +and let clients check and download updates. + +You do not need to prepare a separate database or run a separate migration step. +The container stores SQLite and uploaded artifacts under `/data`, and the app +applies migrations on startup. + +You do need: + +- Docker with Docker Compose; +- `APP_BASE_URL`, `ADMIN_EMAIL`, and `ADMIN_PASSWORD`; +- a persistent `/data` volume; +- for public HTTPS: a reverse proxy in front of the app. + +Post-MVP features such as release channels, signed manifests, delta updates, +S3-compatible storage, and multi-user administration are not part of the current +minimal version. + +## Quick Start With Docker Compose + +1. Copy the example environment file: + + ```bash + cp deploy/update-server.env.example .env + ``` + +2. Edit `.env`. + + For a local first run: + + ```env + APP_BASE_URL=http://127.0.0.1:8080 + ADMIN_EMAIL=admin@example.com + ADMIN_PASSWORD=change-this-before-production + ``` + + For production behind HTTPS: + + ```env + APP_BASE_URL=https://updates.example.com + ADMIN_EMAIL=admin@example.com + ADMIN_PASSWORD=use-a-real-password + ``` + + If `APP_BASE_URL` starts with `https://`, open the admin UI through that + HTTPS URL. Secure cookies are enabled automatically for HTTPS base URLs. + +3. Build and start the container: + + ```bash + docker compose up -d --build + ``` + +4. Check that it is alive: + + ```bash + curl http://127.0.0.1:8080/healthz + ``` + +5. Open the admin UI: + + ```text + http://127.0.0.1:8080/admin + ``` + +After login, create a project, upload a release, create an API key with download +permission, and use that key from a client. + +## Docker Run Example + +Docker Compose is the recommended path, but a direct Docker run works too: + +```bash +docker build -t update-server:latest . + +docker volume create update-server-data + +docker run -d \ + --name update-server \ + --restart unless-stopped \ + -p 127.0.0.1:8080:8080 \ + -e APP_ADDR=0.0.0.0:8080 \ + -e APP_BASE_URL=http://127.0.0.1:8080 \ + -e DATA_DIR=/data \ + -e SQLITE_PATH=/data/db.sqlite \ + -e ARTIFACTS_DIR=/data/artifacts \ + -e MIGRATIONS_DIR=/app/migrations \ + -e TEMPLATES_DIR=/app/web/templates \ + -e STATIC_DIR=/app/web/static \ + -e TRUST_PROXY_HEADERS=false \ + -e ADMIN_EMAIL=admin@example.com \ + -e ADMIN_PASSWORD=change-this-before-production \ + -v update-server-data:/data \ + update-server:latest +``` + +## Proxmox / Caddy Example + +A simple home-server layout is: + +```text +Internet + -> router port forward 80/443 + -> Caddy reverse proxy LXC + -> Docker tools LXC running update-server +``` + +Example: + +```text +Caddy LXC: 192.168.1.50 +Docker tools LXC: 192.168.1.130 +Update Server: 192.168.1.130:18080 +Public URL: https://updates.esenin.site +``` + +In this layout, publish the container port on the Docker tools LXC address: + +```yaml +ports: + - "192.168.1.130:18080:8080" +``` + +Set production environment values: + +```env +APP_BASE_URL=https://updates.esenin.site +ADMIN_EMAIL=admin@example.com +ADMIN_PASSWORD=use-a-real-password +``` + +Then point Caddy at the internal service: + +```caddyfile +updates.esenin.site { + encode gzip zstd + + request_body { + max_size 1GB + } + + reverse_proxy 192.168.1.130:18080 +} +``` + +The admin UI and API can live on the same domain: + +```text +https://updates.esenin.site/admin +https://updates.esenin.site/api/v1 +``` + +## Client API + +The API entrypoint is: + +```text +GET /api/v1 +``` + +Protected client endpoints require: + +```http +Authorization: Bearer +``` + +Common endpoints: + +```text +GET /api/v1/projects +GET /api/v1/projects/{projectSlug}/releases/latest +GET /api/v1/releases/{releaseID} +GET /api/v1/releases/{releaseID}/download +``` + +Example: + +```bash +curl \ + -H "Authorization: Bearer upsk_replace_me" \ + https://updates.example.com/api/v1/projects +``` + +Downloads are intentionally private: uploaded files should not be served by +Caddy or Nginx as static files. Clients download through the application so API +key permissions and project scopes are enforced. + +## Data And Backups + +Persist the whole `/data` directory or Docker volume. It contains: + +```text +/data/db.sqlite +/data/db.sqlite-wal +/data/db.sqlite-shm +/data/artifacts/... +``` + +For live backups, prefer SQLite's online backup command for the database and +archive `/data/artifacts` separately. See `docs/DEPLOYMENT.md` for a fuller +backup and restore flow. + +## Development + +Useful local commands: + +```bash +just run +just test +just build +``` + +Without `just`: + +```bash +go run ./cmd/server +go test ./... +go build -o .bin/update-server ./cmd/server +``` + +Local defaults use `data-dev/` and `http://127.0.0.1:8080` unless overridden by +environment variables. + +## More Docs + +- `docs/DEPLOYMENT.md` - deployment, reverse proxy, backup, and restore notes. +- `deploy/update-server.env.example` - production environment example. +- `deploy/Caddyfile.example` - Caddy reverse proxy example. +- `deploy/nginx.update-server.conf.example` - Nginx reverse proxy example. +- `example/autoupdate.py` - minimal Python auto-update client helper.