feat(docker): add shared-runtime self-hosted deployment

This commit is contained in:
tianma-if committed 2026-08-19 00:10:53 +08:00
1 parent e900e4b615
commit b83e99a9ac
21 files changed
+940 -116

No files matched your search

+142
View File
@@ -0,0 +1,142 @@
# Deploy EdgeEver with Docker
EdgeEver uses the same web application, Hono routes, services, authentication,
OpenAPI document, MCP implementation, and append-only migrations on Cloudflare
and Docker. Only the thin runtime and infrastructure adapters differ: Docker
uses Bun with SQLite and local files (or S3-compatible object storage), while
Cloudflare uses Workers with D1 and R2.
## Requirements
- Docker Engine 24 or later with Docker Compose v2.
- An `amd64` or `arm64` Linux host.
- A reverse proxy with HTTPS when the instance is reachable outside a trusted
local network.
## Start with Compose
Download `compose.yaml`, choose the release you want to run, and provide a
strong instance password:
```sh
export EDGE_EVER_VERSION=vX.Y.Z
export EDGE_EVER_AUTH_PASSWORD='replace-with-a-long-random-password'
docker compose up -d
docker compose ps
```
Open `http://localhost:8787`. The container reports healthy only after the
shared `/api/health` endpoint confirms that authentication, SQLite, and object
storage are ready.
Compose creates one named volume. Everything that must survive a container
replacement is under `/data`:
```text
/data/edgeever.sqlite SQLite database
/data/resources/ local images and attachments
```
The image runs as the non-root `bun` user (UID/GID `1000`). If a NAS requires
a host bind mount instead of the named volume, create the directory first and
grant UID/GID `1000` read/write access.
## Configuration
Common environment variables:
| Variable | Default | Purpose |
| --- | --- | --- |
| `EDGE_EVER_AUTH_USERNAME` | `admin` | Initial administrator username |
| `EDGE_EVER_AUTH_PASSWORD` | none | Initial password; required for a new database |
| `EDGE_EVER_AUTH_PASSWORD_HASH` | none | PBKDF2 hash alternative to the plaintext bootstrap password |
| `EDGE_EVER_SESSION_TTL_DAYS` | `400` | Login session lifetime |
| `EDGE_EVER_IDLE_TIMEOUT_SECONDS` | `120` | Bun streaming idle timeout, from 10 to 255 seconds |
| `EDGE_EVER_STORAGE_ENCRYPTION_KEY` | none | Encrypts saved external object-storage credentials |
| `EDGE_EVER_CREDENTIALS_ENCRYPTION_KEY` | derived | Optional independent AI credential encryption key |
For secrets, append `_FILE` to a supported variable and point it at a Docker
secret, for example `EDGE_EVER_AUTH_PASSWORD_FILE=/run/secrets/auth_password`.
The password/hash, storage encryption keys, and S3 access credentials support
this form. Do not set both the direct variable and its `_FILE` counterpart.
`EDGE_EVER_ALLOW_UNAUTHENTICATED=true` is available for isolated development
only. Do not expose an unauthenticated instance to a network.
## S3-compatible attachment storage
SQLite remains in `/data`, while new attachments can be stored in MinIO, AWS
S3, Alibaba Cloud OSS, Tencent COS, R2, or another compatible service:
```yaml
environment:
EDGE_EVER_STORAGE_BACKEND: s3
EDGE_EVER_S3_ENDPOINT: https://s3.example.com
EDGE_EVER_S3_REGION: us-east-1
EDGE_EVER_S3_BUCKET: edgeever
EDGE_EVER_S3_ACCESS_KEY_ID_FILE: /run/secrets/s3_access_key
EDGE_EVER_S3_SECRET_ACCESS_KEY_FILE: /run/secrets/s3_secret_key
EDGE_EVER_S3_FORCE_PATH_STYLE: "true"
```
Changing the default backend does not migrate historical attachments. Keep
the old backend available until its resources have been exported or migrated.
## HTTPS and network exposure
The container serves HTTP on port `8787`. Terminate HTTPS in a maintained
reverse proxy such as Caddy, Traefik, or Nginx and forward the original host
and client address headers. Do not publish SQLite, `/data`, or an object-store
administration port.
## Backup and restore
Use EdgeEver's ZIP export for portable content backups. Also make a cold copy
of the `/data` volume for complete instance recovery:
1. Run `docker compose stop edgeever` and wait for the shutdown-complete log.
EdgeEver checkpoints SQLite's WAL during graceful shutdown.
2. Copy or snapshot the entire named volume, including the SQLite file and
`resources` directory.
3. Start the service with `docker compose start edgeever`.
Keep `EDGE_EVER_STORAGE_ENCRYPTION_KEY` and any explicitly configured
`EDGE_EVER_CREDENTIALS_ENCRYPTION_KEY` in a separate secret backup. A volume
backup cannot decrypt stored credentials without those keys. When S3 storage
is enabled, back up the bucket separately.
Restore only while EdgeEver is stopped, into an empty volume, and restore the
matching secret keys at the same time. Test backups periodically on a separate
instance.
## Upgrade and rollback
Use immutable release tags instead of `latest` for production:
```sh
export EDGE_EVER_VERSION=vX.Y.Z
docker compose pull
docker compose up -d
docker compose ps
```
The container applies the same append-only `migrations/*.sql` files used by D1
before it starts accepting traffic. Take a backup first. Application rollback
does not reverse a database migration; restore the pre-upgrade volume backup
when a data rollback is required.
To move between Cloudflare and Docker, use EdgeEver's full backup/export and
restore flow. Do not copy a live D1 database file or rewrite migration history.
## Build from source
```sh
docker build --tag edgeever:local .
docker run --rm -p 8787:8787 \
-e EDGE_EVER_AUTH_PASSWORD='replace-with-a-long-random-password' \
-v edgeever-data:/data \
edgeever:local
```
PostgreSQL is not supported in the first Docker release. It remains a future
storage adapter and will not introduce a separate business-code branch.