|
<div class="docs-content" data-render>
|
|
# Deploy and update
|
|
|
|
First deploy, updates, environment, and rollback for the production stack. See also [Production overview](/docs/production.html) and [nginx and networking](/docs/production-nginx.html).
|
|
|
|
## Prerequisites
|
|
|
|
- Docker with the Compose plugin.
|
|
- The repository checked out on the **same host** that runs (or will run) the development server, so they share one database.
|
|
|
|
## Environment
|
|
|
|
Configuration is a single `.env` file in the project root (git-ignored), loaded both by Compose (`env_file`) and by the app at startup (`python-dotenv`). Copy the committed template and edit it:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
| Variable | Default | Purpose |
|
|
|----------|---------|---------|
|
|
| `SECRET_KEY` | insecure placeholder | Session signing. **Change this.** |
|
|
| `DEVPLACE_DATABASE_URL` | unset | Leave unset to share the project-root `devplace.db`. Set only to point elsewhere. |
|
|
| `DEVPLACE_SITE_URL` | empty | Public origin for absolute URLs (SEO, canonical, push). Empty derives from the request. |
|
|
| `PORT` | `10500` | Host port the nginx front door binds. |
|
|
| `NGINX_MAX_BODY_SIZE` | `50m` | nginx upload ceiling. Must be >= `max_upload_size_mb`. |
|
|
| `NGINX_CACHE_ENABLED` | `false` | Enable the nginx micro-cache for proxied GETs. |
|
|
| `NGINX_CACHE_MAX_SIZE` | `1g` | Cache size cap when enabled. |
|
|
| `DEVPLACE_UID` / `DEVPLACE_GID` | `1000` | Host user the app container runs as, so shared files keep dev ownership. Match `id -u` / `id -g`. |
|
|
|
|
Operational behavior (rate limits, registration, maintenance mode, upload size, news cadence) is tuned live from **Admin -> Settings** and stored in `site_settings`; it needs no redeploy.
|
|
|
|
## First deploy
|
|
|
|
```bash
|
|
cp .env.example .env # set SECRET_KEY, PORT, DEVPLACE_SITE_URL
|
|
make docker-up # docker compose up -d (builds on first run)
|
|
```
|
|
|
|
Open `http://<host>:<PORT>`. Useful targets: `make docker-logs` (tail), `make docker-down` (stop), `make docker-build` (rebuild image), `make docker-clean` (down).
|
|
|
|
## Updating
|
|
|
|
Code is bind-mounted, so most updates need no rebuild:
|
|
|
|
```bash
|
|
git pull
|
|
docker compose up -d # restart workers on the new code
|
|
```
|
|
|
|
Rebuild the image only when dependencies change:
|
|
|
|
```bash
|
|
docker compose build && docker compose up -d
|
|
```
|
|
|
|
## Release branch
|
|
|
|
`make deploy` fast-forwards the release branch:
|
|
|
|
```bash
|
|
git checkout production && git merge master && git push origin production
|
|
```
|
|
|
|
On the server, pull `production` and run the update steps above. CI (`.gitea/workflows/test.yaml`) runs the full test suite on every push/PR to `master`, so only tested commits reach `production`.
|
|
|
|
## Rollback
|
|
|
|
Because the container runs host source, rolling back is a git operation:
|
|
|
|
```bash
|
|
git checkout <previous-good-commit>
|
|
docker compose up -d
|
|
```
|
|
|
|
Back up `devplace.db` (and its `-wal`/`-shm`) before a risky change; the schema auto-syncs forward but is not auto-downgraded.
|
|
|
|
## Bare-metal alternative
|
|
|
|
`make prod` runs the same app without containers (`uvicorn ... --workers 2 --proxy-headers`) from the project root, sharing the identical database and files. It binds port 10500 directly, so it conflicts with the Docker front door on the same port - run one or the other, or set a different `PORT`. Keep `DEVPLACE_WEB_WORKERS` in lockstep with `--workers`; see [Multi-worker and concurrency](/docs/production-concurrency.html) for why.
|
|
</div>
|