73 lines
3.2 KiB
Markdown
73 lines
3.2 KiB
Markdown
# Deployment
|
|
|
|
## Install or update
|
|
|
|
On a server with Docker Engine and Compose v2, clone/pull the repository, copy
|
|
`.env.example` to `.env`, set `SITE_URL`, and run:
|
|
|
|
```sh
|
|
docker compose up --build -d
|
|
```
|
|
|
|
Create the owner separately when needed:
|
|
|
|
```sh
|
|
docker compose exec portfolio-app node maintenance.mjs create-user
|
|
```
|
|
|
|
`create-owner` and `reset-password` remain available. Startup never provisions
|
|
an account. See [SELF_HOSTING.md](SELF_HOSTING.md) for private imports, persistent
|
|
volumes, optional Caddy integration, backups, and the one-time upgrade steps.
|
|
|
|
## Gitea Actions
|
|
|
|
Keep the existing trusted `portfolio-ci` runner with Docker/Compose, Bash, Git,
|
|
and OpenSSH. No dedicated Buildx builder, shared image daemon, release manifests,
|
|
or release-directory symlinks are required. The deployment server needs Git,
|
|
Bash, `flock`, Docker/Compose, access to pull this repository, and a checkout on
|
|
`main` at `DEPLOY_PATH`. Configure its `.env` once, just as for manual deployment.
|
|
|
|
Keep these repository Actions secrets:
|
|
|
|
| Secret | Value |
|
|
| --- | --- |
|
|
| `DEPLOY_HOST` | Server hostname/IP |
|
|
| `DEPLOY_USER` | SSH user allowed to run Docker |
|
|
| `DEPLOY_PORT` | Optional SSH port, default 22 |
|
|
| `DEPLOY_PATH` | Absolute server checkout directory |
|
|
| `DEPLOY_SSH_KEY` | Deployment SSH private key |
|
|
| `DEPLOY_KNOWN_HOSTS` | Verified server SSH host-key entry |
|
|
|
|
The server's checkout needs its own Git read access; the deployment SSH key is
|
|
only for reaching the server. Protect the trusted runner from untrusted fork
|
|
code. Fork pull requests do not run this workflow.
|
|
|
|
- **Pull request or manual workflow:** build the production image, including
|
|
TypeScript validation. No browser tests, unit suites, lint, or audit jobs.
|
|
- **Push to main:** SSH to the server, serialize deployments, fast-forward to
|
|
the triggering commit, back up an existing running installation, then run
|
|
`docker compose up --build -d --remove-orphans --wait --wait-timeout 60`.
|
|
An obsolete queued commit is skipped. The image is tagged with its commit SHA.
|
|
|
|
Each deployment builds once on the server, where Docker retains its dependency,
|
|
native-library, and Next.js caches. `NPM_REGISTRY` in the server `.env` selects a
|
|
mirror if needed. The optional Gitea variable of the same name configures PR
|
|
builds. Avoid pruning build caches between deployments.
|
|
|
|
## Timing and recovery
|
|
|
|
The target is under 180 seconds for cached UI-change deployments. Cold builds,
|
|
network transfers, native-library upgrades, and large backups may take longer.
|
|
This change does not benchmark or enforce a wall-clock guarantee. Job timeouts
|
|
allow a first build to finish rather than killing it at the routine-update target.
|
|
|
|
Backups are retained under `backups/before-<commit>-<timestamp>` in the server
|
|
checkout and are ignored by Git. They contain the database, uploads, and generated
|
|
secret; preserve an externally configured secret separately. Copy backups to
|
|
separate storage through your normal backup process.
|
|
|
|
If startup fails after a schema migration, do not simply downgrade the image.
|
|
Restore the matching pre-upgrade backup and older image using the recovery
|
|
instructions in SELF_HOSTING.md. A build failure leaves the running container
|
|
intact; the checkout remains at the attempted commit so the deployment can be retried.
|