d6e5a39546
Signed-off-by: Tony <tonylu@tony-cloud.com>
241 lines
12 KiB
Markdown
241 lines
12 KiB
Markdown
# Shorebird Self-Hosted Server
|
|
|
|
A self-hosted replacement for the hosted Shorebird CodePush API server.
|
|
See `../shorebird/OPEN_SOURCE_REPLACEMENTS.md` for the current audit of public upstream
|
|
Shorebird components and the local replacements for hosted Shorebird services.
|
|
|
|
## Quick Start (Zero Dependencies)
|
|
|
|
By default the server uses **SQLite** + **local filesystem** - no Docker,
|
|
no Postgres, no MinIO needed.
|
|
|
|
### Prerequisites
|
|
- Go 1.23+
|
|
|
|
### 1. Build and run
|
|
|
|
```bash
|
|
make run
|
|
```
|
|
|
|
That's it. The server starts on `http://localhost:8080`. SQLite database
|
|
and file storage are auto-created under the `data/` directory.
|
|
|
|
### 2. Open the Web Dashboard
|
|
|
|
Navigate to **http://localhost:8080** -> Register -> Start managing apps.
|
|
|
|
### 3. (Optional) Use PostgreSQL + MinIO
|
|
|
|
For production deployments that need horizontal scaling:
|
|
|
|
```bash
|
|
# Start infrastructure
|
|
docker compose --profile full up -d
|
|
|
|
# Set backend overrides
|
|
export DB_DRIVER=postgres
|
|
export DATABASE_URL=postgres://shorebird:shorebird@localhost:5432/shorebird?sslmode=disable
|
|
export STORAGE_DRIVER=s3
|
|
export STORAGE_S3_ENDPOINT=localhost:9000
|
|
export STORAGE_S3_ACCESS_KEY=minioadmin
|
|
export STORAGE_S3_SECRET_KEY=minioadmin
|
|
export STORAGE_S3_USE_SSL=false
|
|
|
|
# Then run the server
|
|
make run
|
|
```
|
|
|
|
### Configuration
|
|
|
|
All settings via environment variables. See `.env.example` for the full list.
|
|
|
|
| Variable | Default | Description |
|
|
|----------|---------|-------------|
|
|
| `DB_DRIVER` | `sqlite` | `sqlite` or `postgres` |
|
|
| `DB_PATH` | `data/shorebird.db` | SQLite file path |
|
|
| `STORAGE_DRIVER` | `local` | `local` or `s3` |
|
|
| `STORAGE_LOCAL_DIR` | `data/storage` | Local storage directory |
|
|
| `JWT_SECRET` | *(insecure default)* | Set in production! |
|
|
| `SERVER_PORT` | `8080` | HTTP port |
|
|
| `SERVER_BASE_URL` | `http://localhost:8080` | Public URL for download links |
|
|
| `SMTP_HOST` | *(empty)* | SMTP host for verification/reset emails; empty logs links |
|
|
| `SMTP_PORT` | `587` | SMTP port |
|
|
| `SMTP_FROM` | `shorebird@localhost` | From address for account emails |
|
|
| `PATCH_DELIVERY_ENCRYPTION` | `off` | Set to `per_device_aes_gcm` to enable opt-in encrypted patch delivery |
|
|
| `PATCH_DELIVERY_AES_SECRET` | *(empty)* | Server secret used to derive per-device AES-GCM keys |
|
|
| `PATCH_DELIVERY_CACHE_ENCRYPTED` | `true` | Cache per-device encrypted patch artifacts |
|
|
|
|
### Optional encrypted patch delivery
|
|
|
|
Encrypted delivery is disabled by default so the server remains compatible
|
|
with the public Shorebird updater, which expects plaintext patch bytes. When
|
|
`PATCH_DELIVERY_ENCRYPTION=per_device_aes_gcm` is set, devices that send
|
|
`accept_encrypted_patch=true` and a `client_id` to `/api/v1/patches/check`
|
|
receive a cached AES-GCM ciphertext URL plus encryption metadata.
|
|
|
|
The generated updater `client_id` is a random UUID persisted on first startup.
|
|
Apps using the cloned `shorebird_code_push` package can call
|
|
`ShorebirdUpdater().setDeviceIdOverride(...)` before checking for updates to
|
|
bind delivery to their own stable app/account device id. This id is not a
|
|
secret; the server derives encryption keys from `PATCH_DELIVERY_AES_SECRET`
|
|
and the app/device/patch context.
|
|
|
|
### Account Security and SSO
|
|
|
|
New password registrations must verify email before web, CLI, or API access is allowed. Configure SMTP in `.env`; without SMTP, verification and reset links are printed to the server log for development.
|
|
|
|
On startup, the server ensures a bootstrap admin exists:
|
|
|
|
- Email: `admin@example.com`
|
|
- Password: `admin123`
|
|
|
|
Override with `DEFAULT_ADMIN_EMAIL`, `DEFAULT_ADMIN_PASSWORD`, and `DEFAULT_ADMIN_NAME`. The bootstrap admin is forced to set a new password on first login.
|
|
|
|
Admins can manage these settings in the dashboard:
|
|
|
|
- Casdoor SSO endpoint, app ID, app secret, and organization.
|
|
- Password registration enabled/disabled.
|
|
- SSO registration enabled/disabled.
|
|
- SSO-only registration.
|
|
- User email verification and global admin grants.
|
|
|
|
The first registered account becomes a global admin. Existing SQLite users are marked verified during migration to avoid locking out current installs.
|
|
|
|
### 6. Configure Shorebird CLI
|
|
|
|
```bash
|
|
export SHOREBIRD_HOSTED_URL=http://localhost:8080
|
|
export AUTH_SERVICE_URL=http://localhost:8080/auth
|
|
export SHOREBIRD_TOKEN=<your-jwt-token>
|
|
```
|
|
|
|
Then use `shorebird init`, `shorebird release`, and `shorebird patch` as normal.
|
|
|
|
### 7. Configure device-side `shorebird.yaml`
|
|
|
|
Add your server URL to the Flutter app's `shorebird.yaml`. The CLI
|
|
environment variables make `shorebird release` and `shorebird patch` talk to
|
|
your server, but the packaged app also needs `base_url` so the runtime updater
|
|
checks the same server.
|
|
|
|
```yaml
|
|
app_id: <your-app-uuid>
|
|
base_url: http://your-server.com:8080
|
|
```
|
|
|
|
## API Endpoints
|
|
|
|
### Auth (public)
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| POST | `/auth/register` | Register a new user |
|
|
| POST | `/auth/token` | Login (get JWT) |
|
|
| POST | `/auth/refresh` | Refresh JWT |
|
|
| GET | `/auth/public-settings` | Registration/SSO capabilities for login UI |
|
|
| POST | `/auth/verify-email/request` | Send verification email |
|
|
| GET | `/auth/verify-email` | Verify email by token |
|
|
| POST | `/auth/password-reset/request` | Send password reset email |
|
|
| GET | `/auth/password-reset` | Password reset form |
|
|
| POST | `/auth/password-reset` | Complete password reset |
|
|
| GET | `/auth/sso/login` | Start Casdoor OAuth login |
|
|
| GET | `/auth/sso/callback` | Casdoor OAuth callback |
|
|
|
|
### API v1 (JWT required unless noted)
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/api/v1/users/me` | Get current user |
|
|
| PATCH | `/api/v1/users/me/password` | Change current user's password |
|
|
| POST | `/api/v1/users` | Create user |
|
|
| GET | `/api/v1/apps` | List apps |
|
|
| POST | `/api/v1/apps` | Create app |
|
|
| DELETE | `/api/v1/apps/{appId}` | Delete app |
|
|
| PATCH | `/api/v1/apps/{appId}/transfer` | Transfer app ownership to another organization |
|
|
| POST | `/api/v1/apps/{appId}/channels` | Create channel |
|
|
| GET | `/api/v1/apps/{appId}/channels` | List channels |
|
|
| POST | `/api/v1/apps/{appId}/releases` | Create release |
|
|
| GET | `/api/v1/apps/{appId}/releases` | List releases |
|
|
| PATCH | `/api/v1/apps/{appId}/releases/{releaseId}` | Update release |
|
|
| DELETE | `/api/v1/apps/{appId}/releases/{releaseId}` | Delete release |
|
|
| POST | `/api/v1/apps/{appId}/releases/{releaseId}/artifacts` | Upload release artifact |
|
|
| GET | `/api/v1/apps/{appId}/releases/{releaseId}/artifacts` | Get release artifacts |
|
|
| POST | `/api/v1/apps/{appId}/patches` | Create patch |
|
|
| POST | `/api/v1/apps/{appId}/patches/{patchId}/artifacts` | Upload patch artifact |
|
|
| GET | `/api/v1/apps/{appId}/releases/{releaseId}/patches` | List patches |
|
|
| POST | `/api/v1/apps/{appId}/patches/promote` | Promote patch to channel |
|
|
| GET | `/api/v1/organizations` | List organizations |
|
|
| POST | `/api/v1/organizations` | Create organization |
|
|
| GET | `/api/v1/organizations/{orgId}/users` | List organization users |
|
|
| POST | `/api/v1/organizations/{orgId}/users` | Add/update organization user role |
|
|
| **POST** | **`/api/v1/patches/check`** | **Device patch check (public)** |
|
|
| **POST** | **`/api/v1/patches/events`** | **Device patch event (public)** |
|
|
| GET | `/api/v1/diagnostics/gcp_upload` | Speed test (stub) |
|
|
| GET | `/api/v1/diagnostics/gcp_download` | Speed test (stub) |
|
|
|
|
### Admin: Targeted Device Patching
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| POST | `/api/v1/admin/patches/{patchId}/target-devices` | Restrict patch to device(s) |
|
|
| GET | `/api/v1/admin/patches/{patchId}/target-devices` | List targeted devices |
|
|
| DELETE | `/api/v1/admin/patches/{patchId}/target-devices/{clientId}` | Remove device restriction |
|
|
|
|
### Admin: Users and Settings
|
|
| Method | Path | Description |
|
|
|--------|------|-------------|
|
|
| GET | `/api/v1/admin/users` | List users |
|
|
| POST | `/api/v1/admin/users/{userId}/verify-email` | Force verify a user email |
|
|
| POST | `/api/v1/admin/users/{userId}/admin` | Grant or revoke global admin |
|
|
| GET | `/api/v1/admin/settings` | Get registration and SSO settings |
|
|
| PUT | `/api/v1/admin/settings` | Update registration and SSO settings |
|
|
|
|
## Environment Variables
|
|
|
|
See `.env.example` for all available configuration options.
|
|
|
|
## Architecture
|
|
|
|
```
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Developer Machine │
|
|
│ ┌──────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
|
│ │ Shorebird │ │Artifact │ │ Flutter (forked)│ │
|
|
│ │ CLI │ │Proxy (open) │ │ │ │
|
|
│ └────┬─────┘ └──────┬──────┘ └─────────────────┘ │
|
|
│ │ │ │
|
|
└───────┼───────────────┼───────────────────────────────┘
|
|
│ │
|
|
▼ ▼
|
|
┌──────────────────────────────────────────────────────┐
|
|
│ Self-Hosted Server (Go) │
|
|
│ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │
|
|
│ │ Auth API │ │CodePush │ │ Admin API │ │
|
|
│ │ /auth/* │ │API /api/*│ │ /api/v1/admin/* │ │
|
|
│ └────┬─────┘ └────┬─────┘ └─────────┬──────────┘ │
|
|
│ │ │ │ │
|
|
│ ▼ ▼ ▼ │
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
|
│ │ SQLite / PostgreSQL │ │
|
|
│ │ (apps, releases, patches, artifacts, events) │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
|
│ │ Local FS / MinIO (S3-compatible) │ │
|
|
│ │ shorebird-releases (private) │ │
|
|
│ │ shorebird-patches (public) │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────┘
|
|
▲
|
|
│ (patch check + download)
|
|
│
|
|
┌───────┴───────────────────────────────────────────────┐
|
|
│ End-User Device │
|
|
│ ┌──────────────────────────────────────────────────┐ │
|
|
│ │ Shorebird Updater (Rust, embedded in app) │ │
|
|
│ │ POST /api/v1/patches/check → download patch │ │
|
|
│ └──────────────────────────────────────────────────┘ │
|
|
└──────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## License
|
|
|
|
MIT / Apache 2.0 (matching Shorebird's licensing)
|