Skip to content

- update prod environment files #130

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy-to-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ jobs:
target: production
build-args: |
DEPLOYMENT_PROJECT_VERSION_ARG=${{ env.DEPLOYMENT_PROJECT_VERSION }}
ENVIRONMENT=${{ env.ENVIRONMENT }}
ENVIRONMENT_ARG=${{ env.ENVIRONMENT }}
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
push: true
Expand Down
173 changes: 173 additions & 0 deletions .github/workflows/deploy-to-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: Deploy to prod

concurrency:
group: deploy-prod
cancel-in-progress: false

on:
release:
types: [ published ]
workflow_dispatch:

jobs:
deploy:
environment: prod
runs-on: ubuntu-24.04
name: Deploy to prod
env:
DOCKER_REGISTRY: registry.blumilk.pl
DOCKER_REGISTRY_USER_NAME: robot@blumilkbot-harbor
DOCKER_REGISTRY_PROJECT_NAME: internal-public
DOCKER_REGISTRY_REPO_NAME: lmt
TARGET_DIR_ON_SERVER: /blumilk/deployments/prod/projects
ENVIRONMENT: prod
steps:
- name: set branch name
run: echo "BRANCH_NAME=$GITHUB_REF_NAME" >> $GITHUB_ENV

- name: checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
fetch-depth: 0
ref: ${{ env.BRANCH_NAME }}

- name: sync with main branch
run: |
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git merge --no-commit --no-ff origin/main

- name: set deployment project version
run: echo "DEPLOYMENT_PROJECT_VERSION=$(bash ./environment/.deployment/scripts/version.sh --long)" >> $GITHUB_ENV

- name: set docker image name
run: echo "DOCKER_IMAGE_NAME=${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_REGISTRY_PROJECT_NAME }}/${{ env.DOCKER_REGISTRY_REPO_NAME }}" >> $GITHUB_ENV

- name: fetch server secrets
uses: Infisical/secrets-action@v1.0.8
with:
domain: https://infisical.blumilk.pl
client-id: ${{ secrets.INFISICAL_MACHINE_IDENTITY_GHA_BOT_CLIENT_ID }}
client-secret: ${{ secrets.INFISICAL_MACHINE_IDENTITY_GHA_BOT_CLIENT_SECRET }}
project-slug: blumilk-infra-pv-ih
env-slug: infra
secret-path: /servers/ovh/ns31445530
export-type: env
recursive: true
include-imports: true

- name: set up Docker Buildx
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1

- name: login to Docker Registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
with:
registry: ${{ env.DOCKER_REGISTRY }}
username: ${{ env.DOCKER_REGISTRY_USER_NAME }}
password: ${{ env.HARBOR_ROBOT_BLUMILKBOT_TOKEN }} # masked secret fetched from Infisical

- name: set docker app database image name
run: echo "DOCKER_APP_DATABASE_IMAGE_NAME=${{ env.DOCKER_REGISTRY }}/${{ env.DOCKER_REGISTRY_PROJECT_NAME }}/${{ env.DOCKER_REGISTRY_REPO_NAME }}-postgres" >> $GITHUB_ENV


- name: Docker meta for app database
id: meta-app-database
uses: docker/metadata-action@v5.5.1
with:
images: |
${{ env.DOCKER_APP_DATABASE_IMAGE_NAME }}
tags: |
type=raw,value=${{ inputs.tag }}
type=raw,value=latest
context: workflow

- name: build and push app database image
uses: docker/build-push-action@v5.1.0
with:
context: .
file: ./environment/.docker/postgres/Dockerfile
labels: ${{ steps.meta-app-database.outputs.labels }}
tags: ${{ steps.meta-app-database.outputs.tags }}
push: true
cache-from: type=gha, ref=${{ env.DOCKER_APP_DATABASE_IMAGE_NAME }}-prod-build-cache
cache-to: type=gha, ref=${{ env.DOCKER_APP_DATABASE_IMAGE_NAME }}-prod-build-cache, mode=max

- name: Docker meta for app
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
with:
images: ${{ env.DOCKER_IMAGE_NAME }}
tags: |
type=raw,value=${{ inputs.tag }}
type=raw,value=latest
context: workflow

- name: build and push app image
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5.4.0
with:
context: .
file: ./environment/.docker/app/Dockerfile
target: production
build-args: |
DEPLOYMENT_PROJECT_VERSION_ARG=${{ env.DEPLOYMENT_PROJECT_VERSION }}
ENVIRONMENT_ARG=${{ env.ENVIRONMENT }}
labels: ${{ steps.meta.outputs.labels }}
tags: ${{ steps.meta.outputs.tags }}
push: true
cache-from: type=gha, ref=${{ env.DOCKER_IMAGE_NAME }}-prod-build-cache
cache-to: type=gha, ref=${{ env.DOCKER_IMAGE_NAME }}-prod-build-cache, mode=max

- name: set deployment path on server
run: echo "DEPLOYMENT_PATH_ON_SERVER=${{ env.TARGET_DIR_ON_SERVER }}/${{ env.DOCKER_REGISTRY_PROJECT_NAME }}/${{ env.DOCKER_REGISTRY_REPO_NAME }}" >> $GITHUB_ENV

- name: copy files via ssh
uses: appleboy/scp-action@917f8b81dfc1ccd331fef9e2d61bdc6c8be94634 # v0.1.7
with:
timeout: 10s
command_timeout: 10m
host: ${{ env.SERVER_OVH_NS31445530_IP }} # masked secret fetched from Infisical
port: ${{ env.SERVER_OVH_NS31445530_SSH_PORT }} # masked secret fetched from Infisical
username: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_NAME }} # masked secret fetched from Infisical
key: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_SSH_PRIVATE_KEY }} # masked secret fetched from Infisical
passphrase: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_SSH_PRIVATE_KEY_PASSPHRASE }} # masked secret fetched from Infisical
source: "./environment/.deployment/dev/*,./environment/.deployment/Taskfile.yml"
target: ${{ env.DEPLOYMENT_PATH_ON_SERVER }}
rm: true


- name: fetch project deployment secrets
uses: Infisical/secrets-action@v1.0.8
with:
domain: https://infisical.blumilk.pl
client-id: ${{ secrets.INFISICAL_MACHINE_IDENTITY_GHA_BOT_CLIENT_ID }}
client-secret: ${{ secrets.INFISICAL_MACHINE_IDENTITY_GHA_BOT_CLIENT_SECRET }}
project-slug: lmt-d-hr8
env-slug: prod
secret-path: /deployment
export-type: env
recursive: false
include-imports: false

- name: run deployment script over ssh
uses: appleboy/ssh-action@029f5b4aeeeb58fdfe1410a5d17f967dacf36262 # v1.0.3
with:
timeout: 10s
command_timeout: 10m
host: ${{ env.SERVER_OVH_NS31445530_IP }} # masked secret fetched from Infisical
port: ${{ env.SERVER_OVH_NS31445530_SSH_PORT }} # masked secret fetched from Infisical
username: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_NAME }} # masked secret fetched from Infisical
key: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_SSH_PRIVATE_KEY }} # masked secret fetched from Infisical
passphrase: ${{ env.SERVER_OVH_NS31445530_BLUMILKBOT_USER_SSH_PRIVATE_KEY_PASSPHRASE }} # masked secret fetched from Infisical
script_stop: true
# masked secrets from Infisical: HARBOR_ROBOT_BLUMILKBOT_TOKEN, SOPS_AGE_PROD_SECRET_KEY
script: |
cd ${{ env.DEPLOYMENT_PATH_ON_SERVER }}/environment/.deployment/
mv Taskfile.yml ${{ env.ENVIRONMENT }}/
cd ${{ env.ENVIRONMENT }}/
echo ${{ env.HARBOR_ROBOT_BLUMILKBOT_TOKEN }} | docker login ${{ env.DOCKER_REGISTRY }} --username ${{ env.DOCKER_REGISTRY_USER_NAME }} --password-stdin
export SOPS_AGE_KEY=${{ env.SOPS_AGE_PROD_SECRET_KEY }}
export ENVIRONMENT=${{ env.ENVIRONMENT }}
task deploy
docker images --filter dangling=true | grep "${{ env.DOCKER_IMAGE_NAME }}" | awk '{print $3}'| xargs --no-run-if-empty docker rmi
docker images --filter dangling=true | grep ${{ env.DOCKER_APP_DATABASE_IMAGE_NAME }} | awk '{print $3}'| xargs --no-run-if-empty docker rmi
docker logout ${{ env.DOCKER_REGISTRY }}
4 changes: 4 additions & 0 deletions environment/.deployment/prod/.env.prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
APP_NAME="Legnicki Meetup Technologiczny"
ENVIRONMENT=prod

LMT_HOST_NAME=meetup.legnica.pl
12 changes: 12 additions & 0 deletions environment/.deployment/prod/.env.prod.secrets
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
SMTP_HOST=ENC[AES256_GCM,data:gsgEa6DsB0oNV14+yco=,iv:FJBOhKRaqES6PVaY9ncLAZBV2RT5xiH6bkpi3Yw2bgU=,tag:4E78FAYDX7u8JHa0je1Wpw==,type:str]
SMTP_PORT=ENC[AES256_GCM,data:U3Pm,iv:Y5ib6XItl7RiTlyu3Io/SfYl2mT6oadRZKY3swIX5xA=,tag:mFUcIsRH0kFD7xSAC8V8VQ==,type:str]
SMTP_USERNAME=ENC[AES256_GCM,data:heXTJRlCdd0u13CvBBtoImo0Tw==,iv:mCBh0UkC32VUVFgJUAzVhOOSbcwQQOM8X1yNlY4kP8I=,tag:lGNN+4GVQnvmC871alvoTA==,type:str]
SMTP_PASSWORD=ENC[AES256_GCM,data:sevsBwqvH2/pFhAxAsmb0qAJgP5X,iv:Urrz3z9nuX9dNWtVNz86JlcMjcDX+CNaN2+WHD4qvRA=,tag:tQG8uEviLPOBn3dgUt9kAQ==,type:str]
EMAIL_FROM=ENC[AES256_GCM,data:32onjt+XGK1AAN1lGxmA5w==,iv:G0fF39ZBw4X+9xpFz17TyLNOYv+KNqXrwlie4KSOTlk=,tag:SHHgc7Ebf16LqajdeIrg1g==,type:str]
REGISTRATION_NOTIFICATION_EMAIL=ENC[AES256_GCM,data:JziumVNnCee280LOAUR03z6sc0Ym6Z+TQms=,iv:a4eNP/+zy+y67u07XeyOwWf4Krf12/rR05SLvCMOiX8=,tag:XmnFbggxk6OSc3y8em8i7w==,type:str]
sops_age__list_0__map_enc=-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAybXAxU0xId1JkaXJhTFBM\naTluaGpUengrZWs0d1Zsa1RLNXJZU0dnWDI0ClRVNHdkNVlTeXpOajVZQzFPVlNw\ncHd0aFJWMGlsaDlyam96amtwUDZqdmcKLS0tIFc3RUpUODliV0pHSE5VKzlQY3I0\nM3hkcS9QVFZhUStWbG9qTHEyckF2MzQKy4CH1J67GcmWWjVDL19sxfO0gKDbFC72\nQcLOnN584pxSaXAmUOOzFRJaVIgc9xf2ZfYKBEKMg2ALGH/25GDdQQ==\n-----END AGE ENCRYPTED FILE-----\n
sops_age__list_0__map_recipient=age1ys9k3fkd2cxzkpllfe75gagjrfks45r6x9rhllr4lqvfxx520qaqxtj697
sops_lastmodified=2025-05-19T13:34:09Z
sops_mac=ENC[AES256_GCM,data:txu6bJfxuagxtAO2PtmvHNbx25VFycw/rIN2wrg6XmZsiIR+duABXchrs3NaG72lAYaTqKH0dZ/C/q8CPA1gwfDYdvYHSpHPCagXkKSvfXjKGDQrgIctdqqH9O+S5NRGxG1eIzgSv1fl8wweZv9+PPw1ZdCDSQBNISiABqEz3D8=,iv:UvKBk3FgDTEb7UHKZGZWkIaUP8lQ2PY6hkzDI9S/FSk=,tag:E24BcsaIQWRUr9PjkSdMAw==,type:str]
sops_unencrypted_suffix=_unencrypted
sops_version=3.9.4
76 changes: 76 additions & 0 deletions environment/.deployment/prod/docker-compose.prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
networks:
traefik-proxy:
external: true
lmt-prod:
driver: bridge

volumes:
lmt-prod-postgres-data:
name: lmt-prod-postgres-data

services:
lmt-prod-app:
image: registry.blumilk.pl/internal-public/lmt:prod
container_name: lmt-prod-app-container
pull_policy: always
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 1GB
labels:
- "traefik.enable=true"
- "traefik.http.routers.lmt-prod-app.rule=Host(`${LMT_HOST_NAME}`)"
- "traefik.http.routers.lmt-prod-app.entrypoints=websecure"
- "traefik.http.routers.lmt-prod-app.tls=true"
- "traefik.http.routers.lmt-prod-app.tls.certresolver=lets-encrypt-resolver"
- "traefik.http.routers.lmt-prod-app.middlewares=response-gzip-compress@file"
- "io.portainer.accesscontrol.teams=LMT"
working_dir: /application
volumes:
- ./.env:/application/.env:ro
networks:
- lmt-prod
- traefik-proxy
restart: unless-stopped
env_file:
- .deployment

lmt-prod-database:
image: registry.blumilk.pl/internal-public/lmt-postgres:prod
pull_policy: always
container_name: lmt-prod-database-container
deploy:
mode: replicated
replicas: 1
resources:
limits:
memory: 512M
logging:
driver: "json-file"
options:
max-size: "50m"
max-file: "5"
labels:
- "io.portainer.accesscontrol.teams=LMT"
environment:
- POSTGRES_USER=${DB_USERNAME:? variable DB_USERNAME not set}
- POSTGRES_PASSWORD=${DB_PASSWORD:? variable DB_PASSWORD not set}
- POSTGRES_DB=${DB_DATABASE:? variable DB_DATABASE not set}
- PGDATA=/var/lib/postgresql/data
healthcheck:
test: [ "CMD-SHELL", "pg_isready --dbname ${DB_DATABASE} --username ${DB_USERNAME}" ]
interval: 3s
timeout: 3s
retries: 5
volumes:
- lmt-prod-postgres-data:/var/lib/postgresql/data
networks:
- lmt-prod
restart: unless-stopped
6 changes: 4 additions & 2 deletions environment/.docker/app/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,8 @@ RUN composer install \

FROM node AS frontend-build

ARG ENVIRONMENT
ARG ENVIRONMENT_ARG
ENV ENVIRONMENT=${ENVIRONMENT_ARG}

WORKDIR /app_frontend_dependencies

Expand All @@ -118,7 +119,8 @@ RUN npm run build

FROM base AS production

ARG ENVIRONMENT
ARG ENVIRONMENT_ARG
ENV ENVIRONMENT=${ENVIRONMENT_ARG}

RUN docker-php-ext-install \
opcache
Expand Down
6 changes: 6 additions & 0 deletions environment/prod/app/php-fpm.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[global]
daemonize = no

[www]
listen = /run/php-fpm.sock
listen.owner = nginx
15 changes: 15 additions & 0 deletions environment/prod/app/php.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
[PHP]
memory_limit = 256M
allow_url_fopen = 0
expose_php = 0
log_errors = 1
display_startup_errors = 0
post_max_size = 30M
upload_max_filesize = 30M

[opcache]
opcache.enable = 1
opcache.enable_cli = 1
opcache.memory_consumption = 512
opcache.max_accelerated_files = 20000
opcache.interned_strings_buffer = 16
31 changes: 31 additions & 0 deletions environment/prod/app/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
; For more information on the config file, please see:
; http://supervisord.org/configuration.html

[supervisord]
logfile = /var/log/supervisor/supervisord.log
pidfile = /var/run/supervisord.pid
user = root
nodaemon = true

[program:nginx]
command = nginx
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

[program:php-fpm]
command = php-fpm
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

[program:laravel-queue-worker]
command = php /application/artisan queue:work --timeout=3600 --tries=3
user = www-data
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes = 0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes = 0

1 change: 1 addition & 0 deletions environment/prod/app/vite.prod.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
VITE_APP_NAME="Legnicki Meetup Technologiczny"
15 changes: 15 additions & 0 deletions environment/secops-Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,21 @@ tasks:
ENVIRONMENT: dev
AGE_SECRET_KEY: ${SOPS_AGE_DEV_SECRET_KEY}

encrypt-prod-secrets:
desc: "Encrypt app prod secrets"
cmds:
- task: _encrypt-secrets
vars:
ENVIRONMENT: prod

decrypt-prod-secrets:
desc: "Decrypt app prod secrets"
cmds:
- task: _decrypt-secrets
vars:
ENVIRONMENT: prod
AGE_SECRET_KEY: ${SOPS_AGE_PROD_SECRET_KEY}

_encrypt-secrets:
internal: true
cmds:
Expand Down