116 lines
4.9 KiB
Markdown
116 lines
4.9 KiB
Markdown
# Dyolink
|
|
|
|
Monorepo: **NestJS** backend (`backend/`), **Next.js** frontend (`frontend/`), **Docker** stack under `infrastructure/`.
|
|
|
|
Local development: see **`backend/README.md`** and **`frontend/README.md`**.
|
|
|
|
---
|
|
|
|
## Deploy on your own server (Docker + Gitea)
|
|
|
|
High level: **build container images → push to a registry → server pulls images and runs Compose**. Optionally **Gitea Actions** automates that on every merge to `main` / `master`.
|
|
|
|
### 1. One-time server preparation
|
|
|
|
1. Install **Docker** and **Docker Compose** on the server.
|
|
2. Run **Gitea** with the **container registry** enabled (same host/port you use for `docker login`, e.g. `178.131.50.201:3000`).
|
|
3. Copy the repo (or deploy only `infrastructure/` + secrets). You need at least:
|
|
|
|
- `infrastructure/docker-compose.registry.yml`
|
|
- `infrastructure/nginx/` configs referenced by that compose file
|
|
- `infrastructure/database/init.sql` if used by your Postgres service
|
|
|
|
4. **Secrets on the server** (never commit real values):
|
|
|
|
- Copy `infrastructure/database.staging.env.example` → **`database.staging.env`** (Postgres user/password/db).
|
|
- Copy `infrastructure/backend.staging.env.example` → **`backend.staging.env`** (e.g. `DATABASE_URL`, JWT, pointing at the compose Postgres service name).
|
|
- Put both files in one directory on the server, e.g. `/opt/dyolink/secrets/`.
|
|
|
|
5. **Registry login from the server** (same credentials you use for `docker push`):
|
|
|
|
```bash
|
|
docker login <registry-host>:<port> -u <user>
|
|
```
|
|
|
|
For HTTP registries, Docker may require **`insecure-registries`** on the daemon.
|
|
|
|
### 2. Manual deploy (build images elsewhere, run on server)
|
|
|
|
On your **dev machine** (after successful local builds):
|
|
|
|
```powershell
|
|
$REG = "<registry-host>:<port>"
|
|
$OWN = "<registry-owner>"
|
|
$TAG = "manual"
|
|
|
|
docker build -t "${REG}/${OWN}/dyolink-backend:${TAG}" -t "${REG}/${OWN}/dyolink-backend:latest" ./backend
|
|
|
|
docker build `
|
|
--build-arg NEXT_PUBLIC_API_URL="http://<your-public-ip>:<nginx-port>/api" `
|
|
--build-arg NEXT_PUBLIC_APP_URL="http://<your-public-ip>:<nginx-port>" `
|
|
--build-arg NEXT_PUBLIC_APP_NAME="Dyolink" `
|
|
-t "${REG}/${OWN}/dyolink-frontend:${TAG}" `
|
|
-t "${REG}/${OWN}/dyolink-frontend:latest" `
|
|
./frontend
|
|
|
|
docker push "${REG}/${OWN}/dyolink-backend:${TAG}"
|
|
docker push "${REG}/${OWN}/dyolink-backend:latest"
|
|
docker push "${REG}/${OWN}/dyolink-frontend:${TAG}"
|
|
docker push "${REG}/${OWN}/dyolink-frontend:latest"
|
|
```
|
|
|
|
On the **server**, from `infrastructure/`:
|
|
|
|
1. Create **`deploy.registry.env`** (see `infrastructure/deploy.registry.env.example`):
|
|
|
|
- `REGISTRY_PREFIX=<host>:<port>/<owner>` (no `http://`, no trailing slash)
|
|
- `IMAGE_TAG=latest` or the tag you pushed
|
|
- `STAGING_HTTP_PORT=<host port>` (e.g. `8088` — browser uses `http://<ip>:8088`)
|
|
|
|
2. Set **`DEPLOY_SECRETS_DIR`** to the absolute path of the folder containing `database.staging.env` and `backend.staging.env` (you can export it in the shell or add it to `deploy.registry.env` if your Compose setup expects it).
|
|
|
|
3. Pull and start:
|
|
|
|
```bash
|
|
docker compose -f docker-compose.registry.yml --env-file deploy.registry.env pull backend frontend
|
|
docker compose -f docker-compose.registry.yml --env-file deploy.registry.env up -d
|
|
```
|
|
|
|
The backend container runs **`prisma migrate deploy`** on startup (via entrypoint) when `NODE_ENV=production`, so schema updates apply after you deploy a new image that includes new migrations.
|
|
|
|
### 3. Automatic deploy (Gitea Actions)
|
|
|
|
Workflow file: **`.gitea/workflows/registry-build-deploy.yml`**.
|
|
|
|
**Requirements:**
|
|
|
|
- **Gitea Actions** enabled for the repository.
|
|
- A **self-hosted runner** (with Docker) registered to Gitea — the workflow uses `runs-on: self-hosted`.
|
|
- **Repository → Actions → Variables** (examples):
|
|
|
|
- `REGISTRY_HOST` — e.g. `178.131.50.201:3000`
|
|
- `REGISTRY_OWNER` — image namespace (same as Docker image path after the host), e.g. `admin`
|
|
- `PUBLIC_BASE_URL` — URL users open in the browser, e.g. `http://178.131.50.201:8088` (no trailing slash)
|
|
- `DEPLOY_SECRETS_DIR` — **absolute path on the runner machine** to the folder containing `database.staging.env` and `backend.staging.env`
|
|
- Optional: `STAGING_HTTP_PORT` (defaults to `8088`)
|
|
|
|
- **Repository → Actions → Secrets:**
|
|
|
|
- `REGISTRY_USERNAME`
|
|
- `REGISTRY_PASSWORD` — access token with package read/write (or equivalent)
|
|
|
|
**Trigger:** push to **`main`** or **`master`**, or run the workflow manually (**workflow_dispatch**).
|
|
|
|
The pipeline clones from your Gitea instance, builds and pushes backend/frontend images, then on the runner runs **`docker compose pull`** and **`up -d`** using `infrastructure/docker-compose.registry.yml`.
|
|
|
|
---
|
|
|
|
## Related paths
|
|
|
|
| Path | Role |
|
|
|------|------|
|
|
| `backend/Dockerfile` | API image |
|
|
| `frontend/Dockerfile` | Web image |
|
|
| `infrastructure/docker-compose.registry.yml` | Pull-only staging stack (registry images + nginx + postgres) |
|
|
| `infrastructure/deploy.registry.env.example` | Template for `deploy.registry.env` |
|