chore: configure docker-compose for homelab with task2.beetech.dev domain

- Replace archived MinIO images with community-maintained pgsty images
- Change routing domain to task2.beetech.dev across frontend, backend, and minio
- Avoid port collisions with existing homelab services (postgres port 5434)
- Add .env and *.pem to .gitignore
- Remove legacy deploy/ directory and deploy-main.yml workflow
This commit is contained in:
Gabriel Menezes 2026-10-07 14:56:34 -04:00
parent 437dbbe052
commit 791d184954
7 changed files with 86 additions and 284 deletions

View file

@ -1,158 +0,0 @@
name: Deploy to Hostinger
on:
push:
branches:
- main
workflow_dispatch:
env:
REGISTRY: ghcr.io
FRONTEND_IMAGE_NAME: ${{ github.repository }}-frontend
BACKEND_IMAGE_NAME: ${{ github.repository }}-backend
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "21"
cache: maven
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
cache: npm
cache-dependency-path: frontend/package-lock.json
# - name: Run backend tests
# working-directory: backend
# run: ./mvnw -B test
- name: Run frontend build
working-directory: frontend
run: |
npm ci
npm run build
- name: Log in to GHCR
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract Docker metadata for frontend
id: meta-frontend
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}
tags: |
type=raw,value=latest
type=sha
- name: Extract Docker metadata for backend
id: meta-backend
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}
tags: |
type=raw,value=latest
type=sha
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push frontend image
uses: docker/build-push-action@v6
with:
context: ./frontend
file: ./frontend/Dockerfile
push: true
tags: ${{ steps.meta-frontend.outputs.tags }}
labels: ${{ steps.meta-frontend.outputs.labels }}
build-args: |
VITE_API_URL=${{ secrets.FRONTEND_VITE_API_URL }}
- name: Build and push backend image
uses: docker/build-push-action@v6
with:
context: ./backend
file: ./backend/Dockerfile
push: true
tags: ${{ steps.meta-backend.outputs.tags }}
labels: ${{ steps.meta-backend.outputs.labels }}
- name: Copy deploy files to server
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOSTINGER_HOST }}
username: ${{ secrets.HOSTINGER_USER }}
key: ${{ secrets.HOSTINGER_SSH_KEY }}
port: ${{ secrets.HOSTINGER_PORT || 22 }}
source: "deploy/docker-compose.prod.yml"
target: "${{ secrets.HOSTINGER_APP_PATH }}"
strip_components: 1
- name: Deploy on Hostinger
uses: appleboy/ssh-action@v1.2.0
env:
FRONTEND_IMAGE: ${{ env.REGISTRY }}/${{ env.FRONTEND_IMAGE_NAME }}:latest
BACKEND_IMAGE: ${{ env.REGISTRY }}/${{ env.BACKEND_IMAGE_NAME }}:latest
POSTGRES_USER: ${{ secrets.POSTGRES_USER }}
POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }}
DB_URL: ${{ secrets.DB_URL }}
MP_JWT_VERIFY_ISSUER: ${{ secrets.MP_JWT_VERIFY_ISSUER }}
SMALLRYE_JWT_SIGN_KEY: ${{ secrets.SMALLRYE_JWT_SIGN_KEY }}
MP_JWT_VERIFY_PUBLICKEY: ${{ secrets.MP_JWT_VERIFY_PUBLICKEY }}
GHCR_USERNAME: ${{ secrets.GHCR_USERNAME }}
GHCR_TOKEN: ${{ secrets.GHCR_READ_TOKEN }}
MINIO_ROOT_USER: ${{ secrets.MINIO_ROOT_USER }}
MINIO_ROOT_PASSWORD: ${{ secrets.MINIO_ROOT_PASSWORD }}
MINIO_ENDPOINT: ${{ secrets.MINIO_ENDPOINT }}
MINIO_PUBLIC_URL: ${{ secrets.MINIO_PUBLIC_URL }}
MINIO_BUCKET: ${{ secrets.MINIO_BUCKET }}
with:
host: ${{ secrets.HOSTINGER_HOST }}
username: ${{ secrets.HOSTINGER_USER }}
key: ${{ secrets.HOSTINGER_SSH_KEY }}
port: ${{ secrets.HOSTINGER_PORT || 22 }}
envs: FRONTEND_IMAGE,BACKEND_IMAGE,POSTGRES_USER,POSTGRES_PASSWORD,DB_URL,MP_JWT_VERIFY_ISSUER,SMALLRYE_JWT_SIGN_KEY,MP_JWT_VERIFY_PUBLICKEY,GHCR_USERNAME,GHCR_TOKEN,MINIO_ROOT_USER,MINIO_ROOT_PASSWORD,MINIO_ENDPOINT,MINIO_PUBLIC_URL,MINIO_BUCKET
script: |
set -eu
APP_DIR="${{ secrets.HOSTINGER_APP_PATH }}"
mkdir -p "$APP_DIR"
cd "$APP_DIR"
{
echo "POSTGRES_USER=${POSTGRES_USER}"
echo "POSTGRES_PASSWORD=${POSTGRES_PASSWORD}"
echo "DB_URL=${DB_URL}"
echo "FRONTEND_IMAGE=${FRONTEND_IMAGE}"
echo "BACKEND_IMAGE=${BACKEND_IMAGE}"
echo "MP_JWT_VERIFY_ISSUER=${MP_JWT_VERIFY_ISSUER}"
echo "MINIO_ROOT_USER=${MINIO_ROOT_USER}"
echo "MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}"
echo "MINIO_ENDPOINT=${MINIO_ENDPOINT}"
echo "MINIO_PUBLIC_URL=${MINIO_PUBLIC_URL}"
echo "MINIO_BUCKET=${MINIO_BUCKET}"
printf 'SMALLRYE_JWT_SIGN_KEY="%s"\n' "$SMALLRYE_JWT_SIGN_KEY"
printf 'MP_JWT_VERIFY_PUBLICKEY="%s"\n' "$MP_JWT_VERIFY_PUBLICKEY"
} > .env.production
echo "${GHCR_TOKEN}" | docker login ghcr.io -u "${GHCR_USERNAME}" --password-stdin
docker compose --env-file .env.production -f docker-compose.prod.yml pull
docker compose --env-file .env.production -f docker-compose.prod.yml up -d
docker image prune -f

3
.gitignore vendored
View file

@ -1,3 +1,6 @@
.agents
.DS_Store
.vscode
.env
*.pem

View file

@ -1,7 +1,7 @@
quarkus.http.port=8081
quarkus.http.cors.enabled=true
quarkus.http.cors.origins=https://task.beetech.dev
quarkus.http.cors.origins=https://task2.beetech.dev
quarkus.http.cors.methods=GET,PUT,POST,DELETE,PATCH,OPTIONS
quarkus.http.cors.exposed-headers=Content-Disposition
quarkus.http.cors.access-control-max-age=24H

View file

@ -1,20 +0,0 @@
POSTGRES_USER=beetask
POSTGRES_PASSWORD=change-me
DB_URL=jdbc:postgresql://203.0.113.10:5432/beetask
BACKEND_IMAGE=ghcr.io/owner/repo-backend:latest
FRONTEND_IMAGE=ghcr.io/owner/repo-frontend:latest
QUARKUS_HTTP_CORS_ORIGINS=https://app.example.com
MP_JWT_VERIFY_ISSUER=https://beetech.net
SMALLRYE_JWT_SIGN_KEY_LOCATION=privateKey.pem
MP_JWT_VERIFY_PUBLICKEY_LOCATION=publicKey.pem
# MinIO (object storage for user avatars)
# MINIO_ROOT_USER and MINIO_ROOT_PASSWORD are used both by the MinIO service
# and by the backend as access/secret keys.
MINIO_ROOT_USER=change-me
MINIO_ROOT_PASSWORD=change-me
MINIO_ENDPOINT=http://minio:9000
MINIO_PUBLIC_URL=https://minio.task.beetech.dev
MINIO_BUCKET=avatars

View file

@ -1,94 +0,0 @@
services:
postgres:
image: postgres:16
container_name: bee-task-postgres
restart: unless-stopped
environment:
POSTGRES_USER: ${POSTGRES_USER}
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
POSTGRES_DB: ${POSTGRES_DB:-beetask}
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 10s
timeout: 5s
retries: 5
backend:
image: ${BACKEND_IMAGE}
restart: unless-stopped
environment:
DB_USER: ${POSTGRES_USER}
DB_PASSWORD: ${POSTGRES_PASSWORD}
DB_URL: ${DB_URL}
MP_JWT_VERIFY_ISSUER: ${MP_JWT_VERIFY_ISSUER}
SMALLRYE_JWT_SIGN_KEY: ${SMALLRYE_JWT_SIGN_KEY}
MP_JWT_VERIFY_PUBLICKEY: ${MP_JWT_VERIFY_PUBLICKEY}
MINIO_ENDPOINT: ${MINIO_ENDPOINT}
MINIO_ACCESS_KEY: ${MINIO_ROOT_USER}
MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD}
MINIO_BUCKET: ${MINIO_BUCKET}
MINIO_PUBLIC_URL: ${MINIO_PUBLIC_URL}
depends_on:
postgres:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.backend.rule=Host(`api.task.beetech.dev`)"
- "traefik.http.routers.backend.entrypoints=websecure"
- "traefik.http.routers.backend.tls.certresolver=letsencrypt"
- "traefik.http.services.backend.loadbalancer.server.port=8081"
frontend:
image: ${FRONTEND_IMAGE}
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.frontend.rule=Host(`task.beetech.dev`)"
- "traefik.http.routers.frontend.entrypoints=websecure"
- "traefik.http.routers.frontend.tls.certresolver=letsencrypt"
- "traefik.http.services.frontend.loadbalancer.server.port=80"
minio:
image: minio/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
- minio_data:/data
labels:
- "traefik.enable=true"
- "traefik.http.routers.minio.rule=Host(`minio.task.beetech.dev`)"
- "traefik.http.routers.minio.entrypoints=websecure"
- "traefik.http.routers.minio.tls.certresolver=letsencrypt"
- "traefik.http.services.minio.loadbalancer.server.port=9000"
minio-init:
image: minio/mc:latest
depends_on:
- minio
restart: on-failure
entrypoint: >
/bin/sh -c "
sleep 3 &&
mc alias set local http://minio:9000 $$MINIO_ROOT_USER $$MINIO_ROOT_PASSWORD &&
mc mb --ignore-existing local/avatars &&
mc anonymous set download local/avatars
"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD}
volumes:
postgres_data:
minio_data:

View file

@ -3,42 +3,49 @@ services:
image: postgres:16
container_name: bee-task-postgres
restart: unless-stopped
environment:
POSTGRES_USER: beetask
POSTGRES_PASSWORD: beetask
POSTGRES_DB: beetask
ports:
- "5432:5432"
- "5434:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U beetask"]
interval: 10s
timeout: 5s
retries: 5
networks:
- internal
minio:
image: minio/minio:latest
image: pgsty/minio:latest
restart: unless-stopped
command: server /data --console-address ":9001"
environment:
MINIO_ROOT_USER: ${MINIO_ROOT_USER:-beetask123}
MINIO_ROOT_PASSWORD: ${MINIO_ROOT_PASSWORD:-beetaskpassword}
ports:
- "9000:9000"
- "9001:9001"
volumes:
- minio_data:/data
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.minio.rule=Host(`minio.task2.beetech.dev`)"
- "traefik.http.routers.minio.entrypoints=web"
- "traefik.http.services.minio.loadbalancer.server.port=9000"
- "traefik.http.routers.minio-console.rule=Host(`console.minio.task2.beetech.dev`)"
- "traefik.http.routers.minio-console.entrypoints=web"
- "traefik.http.services.minio-console.loadbalancer.server.port=9001"
minio-init:
image: minio/mc:latest
image: pgsty/mc:latest
depends_on:
- minio
restart: on-failure
@ -52,7 +59,71 @@ services:
mc mb --ignore-existing local/avatars &&
mc anonymous set download local/avatars
"
networks:
- internal
backend:
build:
context: ./backend
dockerfile: Dockerfile
container_name: bee-task-backend
restart: unless-stopped
expose:
- "8081"
environment:
DB_USER: beetask
DB_PASSWORD: beetask
DB_URL: jdbc:postgresql://postgres:5432/beetask
QUARKUS_HTTP_CORS_ORIGINS: https://task2.beetech.dev
MP_JWT_VERIFY_ISSUER: ${MP_JWT_VERIFY_ISSUER}
SMALLRYE_JWT_SIGN_KEY: ${SMALLRYE_JWT_SIGN_KEY}
MP_JWT_VERIFY_PUBLICKEY: ${MP_JWT_VERIFY_PUBLICKEY}
MINIO_ENDPOINT: http://minio:9000
MINIO_ACCESS_KEY: ${MINIO_ROOT_USER:-beetask123}
MINIO_SECRET_KEY: ${MINIO_ROOT_PASSWORD:-beetaskpassword}
MINIO_BUCKET: avatars
MINIO_PUBLIC_URL: http://localhost:9000
depends_on:
postgres:
condition: service_healthy
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.backend.rule=Host(`api.task2.beetech.dev`)"
- "traefik.http.routers.backend.entrypoints=web"
- "traefik.http.services.backend.loadbalancer.server.port=8081"
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
VITE_API_URL: ${VITE_API_URL:-https://api.task2.beetech.dev}
container_name: bee-task-frontend
restart: unless-stopped
expose:
- "80"
depends_on:
- backend
networks:
- proxy
- internal
labels:
- "traefik.enable=true"
- "traefik.docker.network=proxy"
- "traefik.http.routers.frontend.rule=Host(`task2.beetech.dev`)"
- "traefik.http.routers.frontend.entrypoints=web"
- "traefik.http.services.frontend.loadbalancer.server.port=80"
volumes:
postgres_data:
minio_data:
networks:
proxy:
external: true
internal:
driver: bridge

View file

@ -1 +1 @@
VITE_API_URL=https://api.task.beetech.dev
VITE_API_URL=https://api.task2.beetech.dev