Files
my-protfolio/DEPLOYMENT.md

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.