chg: pkg: implement CD script to Gitea and add docs to the process #4
Some checks failed
Deploy to Production / deploy (push) Has been cancelled
Some checks failed
Deploy to Production / deploy (push) Has been cancelled
This commit is contained in:
@@ -10,10 +10,9 @@ APP_SECRET=changethis
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# Configure your db driver and server_version in config/packages/doctrine.yaml
|
||||
DATABASE_URL=mysql://db_user:db_password@127.0.0.1:3306/db_name
|
||||
# Docker PostgreSQL is exposed on port 15432 — use that for bare-metal dev.
|
||||
# Replace POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB with the values from your .env.
|
||||
DATABASE_URL=postgresql://POSTGRES_USER:POSTGRES_PASSWORD@127.0.0.1:15432/POSTGRES_DB?serverVersion=18&charset=utf8
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> google/recaptcha ###
|
||||
|
||||
19
.gitea/workflows/deploy.yml
Normal file
19
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Deploy to Production
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
steps:
|
||||
- name: Deploy
|
||||
run: |
|
||||
set -e
|
||||
cd "${{ vars.PROD_APP_DIR }}"
|
||||
git fetch --tags
|
||||
git checkout "${{ gitea.ref_name }}"
|
||||
printf '%s' '${{ secrets.PROD_ENV_FILE }}' > .env
|
||||
docker compose up -d --build
|
||||
@@ -9,7 +9,7 @@ COPY vite.config.js ./
|
||||
COPY assets/ assets/
|
||||
COPY public/ public/
|
||||
|
||||
RUN bun run build && cp -r node_modules/@fortawesome/fontawesome-free/webfonts public/build/webfonts
|
||||
RUN bun run build
|
||||
|
||||
FROM dunglas/frankenphp:latest
|
||||
|
||||
|
||||
106
README.md
106
README.md
@@ -154,6 +154,7 @@ services:
|
||||
mail:
|
||||
image: mailhog/mailhog:latest
|
||||
ports:
|
||||
- "1025:1025"
|
||||
- "8025:8025"
|
||||
```
|
||||
|
||||
@@ -174,6 +175,111 @@ Open the web UI at **http://localhost:8025** to inspect them.
|
||||
|
||||
---
|
||||
|
||||
## Deploying to production
|
||||
|
||||
Releases are automated via Gitea Actions. Pushing a tag that starts with `v` (e.g. `v2026.01`) triggers the workflow at `.gitea/workflows/deploy.yml`.
|
||||
The job runs on a **self-hosted runner** installed on the production server — the server only needs an outbound connection to Gitea, no open SSH port required.
|
||||
The `app` image is rebuilt with the new code; the database and storage containers are untouched so all data is preserved.
|
||||
|
||||
### Gitea repository variables and secrets
|
||||
|
||||
**Variable** (plaintext, editable — **Repository → Settings → Variables**):
|
||||
|
||||
| Variable | Value |
|
||||
|---|---|
|
||||
| `PROD_APP_DIR` | Absolute path on the server (e.g. `/var/www/mineseeker`) |
|
||||
|
||||
**Secret** (encrypted, write-only — **Repository → Settings → Secrets**):
|
||||
|
||||
| Secret | Value |
|
||||
|---|---|
|
||||
| `PROD_ENV_FILE` | Full content of the production `.env` file (see below) |
|
||||
|
||||
The workflow writes `PROD_ENV_FILE` to `.env` on every deploy, so you never need to manage the file on the server manually. To update a credential, overwrite the secret in Gitea and push a new tag.
|
||||
|
||||
#### `PROD_ENV_FILE` contents
|
||||
|
||||
Paste the filled-in `.env` file as the secret value:
|
||||
|
||||
```dotenv
|
||||
APP_ENV=prod
|
||||
APP_SECRET="<openssl rand -hex 32>"
|
||||
|
||||
DATABASE_URL=postgresql://POSTGRES_USER:POSTGRES_PASSWORD@db:5432/POSTGRES_DB?serverVersion=18&charset=utf8
|
||||
|
||||
POSTGRES_USER=mineseeker
|
||||
POSTGRES_PASSWORD="<strong password>"
|
||||
POSTGRES_DB=mineseeker
|
||||
POSTGRES_VERSION=18
|
||||
|
||||
MINIO_ROOT_USER=mineseeker
|
||||
MINIO_ROOT_PASSWORD="<strong password>"
|
||||
MINIO_ENDPOINT=http://minio:9000
|
||||
MINIO_PUBLIC_URL=https://minio.mineseeker.hu
|
||||
|
||||
MAILER_DSN=smtp://mail:25?verify_peer=0
|
||||
MAIL_DOMAIN=mineseeker.hu
|
||||
|
||||
RECAPTCHA_SITE_KEY="<your reCAPTCHA v3 site key>"
|
||||
RECAPTCHA_SECRET_KEY="<your reCAPTCHA v3 secret key>"
|
||||
|
||||
MERCURE_URL=https://mineseeker.hu/.well-known/mercure
|
||||
MERCURE_PUBLIC_URL=https://mineseeker.hu/.well-known/mercure
|
||||
MERCURE_JWT_SECRET="<generated by make mercure-jwt>"
|
||||
MERCURE_JWT_TOKEN="<generated by make mercure-jwt>"
|
||||
MERCURE_SUBSCRIBER_JWT="<generated by make mercure-jwt>"
|
||||
|
||||
APP_PUBLIC_HOSTNAME=mineseeker.hu
|
||||
WEBAUTHN_RP_ID=mineseeker.hu
|
||||
WEBAUTHN_ORIGIN=https://mineseeker.hu
|
||||
```
|
||||
|
||||
### Production server: one-time setup
|
||||
|
||||
The server needs Docker, Git, and a self-hosted `act_runner` registered against the Gitea repository. Bun and Composer run inside the multi-stage Dockerfile, so they are not needed on the server.
|
||||
|
||||
#### 1. Clone the repository
|
||||
|
||||
```bash
|
||||
git clone https://gitea.mineseeker.hu/youruser/mineseeker.git /var/www/mineseeker
|
||||
```
|
||||
|
||||
#### 2. Generate Mercure JWT tokens (run once locally)
|
||||
|
||||
```bash
|
||||
composer install # only needed for this step
|
||||
make mercure-jwt
|
||||
```
|
||||
|
||||
Copy the three printed values into the `PROD_ENV_FILE` secret.
|
||||
|
||||
#### 5. First deploy
|
||||
|
||||
Trigger it by pushing the first tag:
|
||||
|
||||
```bash
|
||||
git tag v2026.01
|
||||
git push origin v2026.01
|
||||
```
|
||||
|
||||
This writes `.env`, builds the Docker image, starts all services, runs migrations, and initialises the MinIO buckets automatically via `minio_init`.
|
||||
|
||||
#### 6. Verify
|
||||
|
||||
```bash
|
||||
docker compose ps # all services should be healthy/running
|
||||
docker compose logs app # look for "Starting FrankenPHP"
|
||||
```
|
||||
|
||||
### Releasing
|
||||
|
||||
```bash
|
||||
git tag v2026.01
|
||||
git push origin v2026.01
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## License
|
||||
|
||||
LGPL-3.0 — see [LICENSE](LICENSE) for details.
|
||||
|
||||
@@ -4,6 +4,7 @@ services:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
restart: unless-stopped
|
||||
container_name: '${APP_NAME}-app'
|
||||
ports:
|
||||
- "10080:80"
|
||||
environment:
|
||||
@@ -42,6 +43,7 @@ services:
|
||||
minio:
|
||||
image: minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1
|
||||
restart: unless-stopped
|
||||
container_name: '${APP_NAME}-minio'
|
||||
command: server /data --console-address ":9001"
|
||||
ports:
|
||||
- "9000:9000"
|
||||
@@ -60,6 +62,7 @@ services:
|
||||
minio_init:
|
||||
image: minio/minio:RELEASE.2025-09-07T16-13-09Z-cpuv1
|
||||
restart: "no"
|
||||
container_name: '${APP_NAME}-minio-init'
|
||||
depends_on:
|
||||
minio:
|
||||
condition: service_healthy
|
||||
@@ -72,6 +75,7 @@ services:
|
||||
mail:
|
||||
image: boky/postfix:latest
|
||||
restart: unless-stopped
|
||||
container_name: '${APP_NAME}-mail'
|
||||
environment:
|
||||
ALLOWED_SENDER_DOMAINS: ${MAIL_DOMAIN:-localhost}
|
||||
RELAYHOST: ${MAIL_RELAYHOST:-}
|
||||
@@ -82,6 +86,7 @@ services:
|
||||
db:
|
||||
image: postgres:${POSTGRES_VERSION:-latest}-alpine
|
||||
restart: unless-stopped
|
||||
container_name: '${APP_NAME}-db'
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"watch": "vite build --watch",
|
||||
"build": "vite build",
|
||||
"build": "vite build && cp -r node_modules/@fortawesome/fontawesome-free/webfonts public/build/webfonts",
|
||||
"lint": "eslint assets/js/"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user