Skip to content
Merged
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
9 changes: 9 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# direnv: automatically activate flox environment and export helpers
use flake || true
if command -v flox >/dev/null 2>&1; then
eval "$(flox activate --sh --impure)"
fi
# Put repo scripts on PATH when opted-in via .git/safe
if [ -d .git/safe ]; then
PATH_add packages/scripts/bin
fi
4 changes: 3 additions & 1 deletion .flox/env/manifest.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ pnpm_10.pkg-path = "pnpm_10"
go.pkg-path = "go"
go.version = "1.25.0"
golangci-lint.pkg-path = "golangci-lint"
dotenvx.pkg-path = "dotenvx"
# sops + age for secrets management
sops.pkg-path = "sops"
age.pkg-path = "age"
awscli.pkg-path = "awscli"
ripgrep.pkg-path = "ripgrep"
uv.pkg-path = "uv"
Expand Down
10 changes: 6 additions & 4 deletions .github/workflows/deploy-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} # You can generate a Fly API token in your account settings
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Required for commenting on pull requests for private repos
NODE_ENV: production
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
SOPS_KMS_KEY: ${{ secrets.SOPS_KMS_KEY }}

jobs:
deploy-preview:
Expand Down Expand Up @@ -56,15 +57,16 @@ jobs:
- id: deploy
uses: "superfly/fly-pr-review-apps@1.5.0"
with:
secrets: DATABASE_URL=$DATABASE_URL DOTENV_PRIVATE_KEY_PRODUCTION="$DOTENV_PRIVATE_KEY_PRODUCTION"
secrets: DATABASE_URL=$DATABASE_URL SOPS_AGE_KEY="$SOPS_AGE_KEY" SOPS_KMS_KEY="$SOPS_KMS_KEY"
config: apps/nextjs/fly.toml
build_args: |
ENV=production
DOTENV_PRIVATE_KEY_PRODUCTION=${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_KMS_KEY=${{ secrets.SOPS_KMS_KEY }}
org: acme
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
SOPS_KMS_KEY: ${{ secrets.SOPS_KMS_KEY }}


- name: Comment on Pull Request
Expand Down
17 changes: 10 additions & 7 deletions .github/workflows/fly-deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ on:
branches:
- replace-me # Replace with your production branch, e.g., "main" or "master"
env:
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
SOPS_KMS_KEY: ${{ secrets.SOPS_KMS_KEY }}
jobs:
deploy:
name: Deploy app
Expand All @@ -17,11 +18,12 @@ jobs:
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: |
echo "validating env vars"
[ -z "$DOTENV_PRIVATE_KEY_PRODUCTION" ] && echo "missing DOTENV_PRIVATE_KEY_PRODUCTION" && exit 1 || echo "✅ Environment variables are valid"
flyctl deploy --config apps/nextjs/fly.toml --dockerfile apps/nextjs/Dockerfile --build-arg DOTENV_PRIVATE_KEY_PRODUCTION="$DOTENV_PRIVATE_KEY_PRODUCTION" -e DOTENV_PRIVATE_KEY_PRODUCTION="$DOTENV_PRIVATE_KEY_PRODUCTION"
echo "Using SOPS for envs (AGE or KMS)"
flyctl deploy --config apps/nextjs/fly.toml --dockerfile apps/nextjs/Dockerfile --build-arg SOPS_KMS_KEY="$SOPS_KMS_KEY" -e SOPS_AGE_KEY="$SOPS_AGE_KEY" -e SOPS_KMS_KEY="$SOPS_KMS_KEY"
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
SOPS_KMS_KEY: ${{ secrets.SOPS_KMS_KEY }}
- name: Setup tmate session
if: ${{ failure() }}
uses: mxschmitt/action-tmate@v3
Expand All @@ -34,11 +36,12 @@ jobs:
- uses: superfly/flyctl-actions/setup-flyctl@master
- run: |
echo "validating env vars"
[ -z "$DOTENV_PRIVATE_KEY_PRODUCTION" ] && echo "missing DOTENV_PRIVATE_KEY_PRODUCTION" && exit 1 || echo "✅ Environment variables are valid"
flyctl deploy --config apps/travel-assistant-api/fly.toml --dockerfile apps/travel-assistant-api/Dockerfile --build-arg DOTENV_PRIVATE_KEY_PRODUCTION="$DOTENV_PRIVATE_KEY_PRODUCTION" -e DOTENV_PRIVATE_KEY_PRODUCTION="$DOTENV_PRIVATE_KEY_PRODUCTION"
echo "Using SOPS for envs (AGE or KMS)"
flyctl deploy --config apps/travel-assistant-api/fly.toml --dockerfile apps/travel-assistant-api/Dockerfile --build-arg SOPS_KMS_KEY="$SOPS_KMS_KEY" -e SOPS_AGE_KEY="$SOPS_AGE_KEY" -e SOPS_KMS_KEY="$SOPS_KMS_KEY"
env:
FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
SOPS_AGE_KEY: ${{ secrets.SOPS_AGE_KEY }}
SOPS_KMS_KEY: ${{ secrets.SOPS_KMS_KEY }}
# Optional: Uncomment the following lines to set up a tmate session for debugging if the deployment fails
# - name: Setup tmate session
# if: ${{ failure() }}
Expand Down
9 changes: 9 additions & 0 deletions .sops.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# SOPS config: default to AGE (set recipients when you encrypt)
# For public template we ship an empty rule; pass recipients via CLI:
# sops -e --age "$(age-keygen -y age.key)" <file>
creation_rules:
- path_regex: ".*\\.sops$"
age: []
kms: []
gcp_kms: []
azure_keyvault: []
24 changes: 10 additions & 14 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,14 @@ prune: ## Remove all unused Docker resources
.PHONY: ci-build-nextjs
ci-build-nextjs: ## Build Next.js for CI
docker build -f apps/nextjs/Dockerfile \
--build-arg DOTENV_PRIVATE_KEY_PRODUCTION="$(DOTENV_PRIVATE_KEY_PRODUCTION)" \
--build-arg SOPS_KMS_KEY="$(SOPS_KMS_KEY)" \
--tag voytravel-nextjs:latest .

.PHONY: ci-build-api
ci-build-api: ## Build Python API for CI
docker build -f apps/travel-assistant-api/Dockerfile \
--build-arg ENV=production \
--build-arg DOTENV_PRIVATE_KEY_PRODUCTION="$(DOTENV_PRIVATE_KEY_PRODUCTION)" \
--build-arg SOPS_KMS_KEY="$(SOPS_KMS_KEY)" \
--tag voytravel-api:latest .

.PHONY: test-build
Expand All @@ -87,21 +87,17 @@ test-build: ## Test production builds locally

.PHONY: env-decrypt-dev
env-decrypt-dev:
exec dotenvx decrypt \
-fk .env.keys \
-f apps/nextjs/.env.development
@[ -f apps/nextjs/.env.development.sops ] || { echo "No apps/nextjs/.env.development.sops"; exit 1; }
sops -d apps/nextjs/.env.development.sops > apps/nextjs/.env.development
.PHONY: env-encrypt-dev
env-encrypt-dev:
dotenvx encrypt \
-fk .env.keys \
-f apps/nextjs/.env.development
@[ -f apps/nextjs/.env.development ] || { echo "No apps/nextjs/.env.development"; exit 1; }
sops -e -i apps/nextjs/.env.development
.PHONY: env-decrypt-prod
env-decrypt-prod:
dotenvx decrypt \
-fk .env.keys \
-f apps/nextjs/.env.production
@[ -f apps/nextjs/.env.production.sops ] || { echo "No apps/nextjs/.env.production.sops"; exit 1; }
sops -d apps/nextjs/.env.production.sops > apps/nextjs/.env.production
.PHONY: env-decrypt-prod
env-encrypt-prod:
dotenvx encrypt \
-fk .env.keys \
-f apps/nextjs/.env.production
@[ -f apps/nextjs/.env.production ] || { echo "No apps/nextjs/.env.production"; exit 1; }
sops -e -i apps/nextjs/.env.production
20 changes: 8 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,14 @@ To get it running, follow the steps below:
# Install dependencies
pnpm i

# Configure environment variables
# Environment variables are checked in but encrypted for security. The encryption
# keys are store in .env.keys and should not be checked in.
echo << EOF > .env.keys
#/------------------!DOTENV_PRIVATE_KEYS!-------------------/
#/ private decryption keys. DO NOT commit to source control /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
# .env.development
DOTENV_PRIVATE_KEY_DEVELOPMENT=32481a02ef873fd2386669251ef0d7d5083f76465f92e013cc9948c403fcc20b

EOF
# Configure environment variables with SOPS (AGE by default)
# Generate an age keypair (store key locally; do not commit):
# age-keygen -o age.key
# Export recipient for this shell (or set in your profile):
# export SOPS_AGE_RECIPIENTS="$(age-keygen -y age.key)"
# Create encrypted envs (edit will create if missing):
# sops apps/nextjs/.env.development.sops
# sops apps/nextjs/.env.production.sops

# Push the Drizzle schema to the database
pnpm db:push
Expand Down
1 change: 0 additions & 1 deletion apps/expo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
"@acme/tailwind-config": "workspace:*",
"@acme/ui": "workspace:*",
"@better-auth/expo": "catalog:",
"@dotenvx/dotenvx": "^1.51.0",
"@expo-google-fonts/bebas-neue": "^0.4.1",
"@expo-google-fonts/montserrat": "^0.4.2",
"@expo-google-fonts/source-code-pro": "^0.4.1",
Expand Down
7 changes: 2 additions & 5 deletions apps/nextjs/.env.development
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY_DEVELOPMENT="022e695fdc17e1866bd101e153c8a5e9fe7eb4331669b0e9c33ed8a9e6423a8d6c"
# Managed with SOPS. Use `.env.development.sops` for secrets.
SOPS_MANAGED=1

# .env.development
# Since .env is gitignored, you can use .env.example to build a new `.env` file when you clone the repo.
Expand Down
31 changes: 14 additions & 17 deletions apps/nextjs/.env.production
Original file line number Diff line number Diff line change
@@ -1,45 +1,42 @@
#/-------------------[DOTENV_PUBLIC_KEY]--------------------/
#/ public-key encryption for .env files /
#/ [how it works](https://dotenvx.com/encryption) /
#/----------------------------------------------------------/
DOTENV_PUBLIC_KEY_PRODUCTION="02ce457bd09c083c2dfd806e80e7728cd479bc74785154d7eb5882fe15de6ade85"
# Managed with SOPS. Use `.env.production.sops` for secrets.
SOPS_MANAGED=1

# .env.production
# This file will be committed to version control, so make sure not to have any secrets in it.
# If you are cloning this repo, create a copy of this file named `.env` and populate it with your secrets.

# The database URL is used to connect to your Supabase database.
POSTGRES_URL="encrypted:BB71wsjg6Dcl4pHxqSE7ESd1RAtTx7H0B4njevyuEWUmc8A9DziRwiRDvhHnX4g2x+DXSJrBJwgYNzWSLjOT33OLSf/Viq9yYXpmDKZA/GQFmQktq5d+aGimdYCMJCWLGEZjnsHHTR8xQMsZLdyVIqgQk8fZpJ3nD8BQ1BVMuwrKx9duDu9HdQnzVWm+GA=="
POSTGRES_URL=""

# The URL of your Next.js app, used for redirects and links.
NEXTJS_URL='encrypted:BPzL8geQSL0mfhZdJuLsCeOywMcNffUIKBt9DaocdnWVcCwag/MoZ6RuUcob25a7DmRjGAo92WKyGYfzn2ROt9PwjJsUfuhcLt+gJjkXlp7C16MMlvxXOlge0qJ17ii8LfidnBrM4YxlRDrHeXfLPGYak6BBsA=='
NEXTJS_URL=''

# Expo web app URL, used for redirects and links.
EXPO_WEB_URL='encrypted:BKK0Vv5n3PLuj3s3M7eepx5PZiOHjSpY3UOupPqn2+O5thi3KjEyudf0X90y2Atonl8PkI7qxbxE4TXdwwZRToFfNpiQaPSa08ipIpKJwOG25nKjUCpH5LctNdXE5DXIGmIPBOTT+cQllUCQNUf+7CB1EV+WXg=='
EXPO_WEB_URL=''

# You can generate the secret via 'openssl rand -base64 32' on Unix
# @see https://www.better-auth.com/docs/installation
AUTH_SECRET='encrypted:BONPpCzlr0cSmzOhGUJUm9pH9g0DDaDSGk8inZczzGUA9INDpSllJRCor4AQQ2+TUEhtBh2M9bVxzujat4hmVVXe4MxY+y/BhVV+waOz+mUz7cPNX9702EpMTqAr29q/bSPYwPgtjwNqdXr3'
AUTH_SECRET=''

# Preconfigured OAuth providers: Add your credentials here to dynamically enable or
# disable them in the auth package.
# @see https://www.better-auth.com/docs/authentication/oauth-providers
# Discord
AUTH_DISCORD_ID='encrypted:BDa5IhK9ihhy/KnFb9vTUNJpGPjX8E3HFqXEWNxPZ7Fnah+1gPFTdc75A3l3+E/cMgz5z7UUUEt/33Z0EdCxQzH1hM/CrNhuSYLd6DQcjdR5nIavRhoFIQjWR2q3J7xwzQ=='
AUTH_DISCORD_SECRET='encrypted:BLf+/Pdhl40socnYD3DMYMjF4hq4GX3NfqOMftOALqOVV+rb4P3vrSswIBL8lLb6w/uQG04V6WL4iTgWUPFbfohvMmXSuqBVBB+9S1O4BsIKAhjzWkCJes1kIuUak639cA=='
AUTH_DISCORD_ID=''
AUTH_DISCORD_SECRET=''
# GitHub
AUTH_GITHUB_ID='encrypted:BEn+jRLawZSl+da0+LWwdCKWhAVlxP9W5/jsKOcxvVJeEc+FTzt9/Q7ZVO6FzrnGHXThb1Xb1No76B2uYNNgq4JvjZjZTH4VGkBn4uWhFMhB9l0W1bTH3fgFrMTpt2/KiA=='
AUTH_GITHUB_SECRET='encrypted:BIXVcH18YteMUuxS970qPyjzMhOwMAf9dlg2GwInJKKCMLxEbsKrYv9YNU6Bsvnf1oGk2NMdYbufogAZHYG8ij62ktOGJZGoKUJ/K/VopiKEzHhVjq7V9ZkOx8XknMpqqw=='
AUTH_GITHUB_ID=''
AUTH_GITHUB_SECRET=''
# Google
AUTH_GOOGLE_ID='encrypted:BDSlL/6yjHDoeQcHO3eAKXe8g1UsFUyedSya9lnG9cErZYuM0BfMq5/PadWNisoC2Gqh5bur15g1jStvOdL5ydfxRrrIZ44ZXJsUT50fuILy4MrUtmSHX+ivCDTJAQdbrg=='
AUTH_GOOGLE_SECRET='encrypted:BK/QXzE987H+6okt82FGGGhv9n1luT+ndDmK554lAF4puDir+/5yA3S7RwoqkKtB7MBiGPodMr9drUMwu0vEg5YR8UCSx+iCrJOyQVladMVCd+ZUSjky7rnVcyP+vA4A4w=='
AUTH_GOOGLE_ID=''
AUTH_GOOGLE_SECRET=''

# In case you're using the Auth Proxy (apps/auth-proxy)
# AUTH_REDIRECT_PROXY_URL='https://auth.your-server.com/r'

# SendGrid is preconfigured, delete if you want to use another email provider.
# @see https://next-auth.js.org/configuration/providers/email
SENDGRID_API_KEY='encrypted:BGp6WnoxkzCGEGAj85g/epiXWPlkJDLEaQF2SbA/2STmef5EF0pMvMYGl6mWej62CSldB+SPr1BtktHEWR6FE426dd0482iJS0yst3XAa3OZQI0f70SAefaCiYh0mWilEA=='
SENDGRID_API_KEY=''

# Disable this in production to prevent metro from bundling storybook
STORYBOOK_ENABLED=encrypted:BO51SJiW3UewXmRU/i6aQJCXOACegmPA7j3doI4W/bGSb6vYTNJ9OqGu+57hkRSua5meMo8hcMnA9znXOSmIEdurcDJ/te1ThQ4viJs9Qukuva+0q5bNIzKhArTnTO6vYAzA2MY=
STORYBOOK_ENABLED=
8 changes: 4 additions & 4 deletions apps/nextjs/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ FROM node:${NODE_VERSION}-alpine AS runner
WORKDIR /app

# Runtime deps
RUN apk add --no-cache libc6-compat curl bash
RUN apk add --no-cache libc6-compat curl bash sops age

# Enable pnpm in runtime and set non-root install locations
RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate
Expand All @@ -61,7 +61,7 @@ ENV PATH="/home/nextjs/.npm-global/bin:$PNPM_HOME:$PATH"
RUN mkdir -p /home/nextjs/.local/share/pnpm /home/nextjs/.pnpm-store /home/nextjs/.npm-global

# Optional: tools used by start.sh
RUN npm install -g @dotenvx/dotenvx@latest
# Using nix/flox or local install for extras; keep minimal
RUN npm install -g drizzle-kit

# Don't run production as root
Expand All @@ -80,8 +80,8 @@ COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/public ./apps/nextj
# Copy database package if needed at runtime (e.g., migrations)
COPY --from=installer --chown=nextjs:nodejs /app/packages/db ./packages/db

# Optionally include production env files
COPY --chown=nextjs:nodejs .env.production* ./
# Optionally include production env files from app workspace
COPY --from=installer --chown=nextjs:nodejs /app/apps/nextjs/.env.production* ./

# Start script
COPY --chown=nextjs:nodejs --chmod=0755 apps/nextjs/start.sh ./start.sh
Expand Down
3 changes: 1 addition & 2 deletions apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"lint": "biome lint .",
"start": "pnpm with-env next start",
"typecheck": "tsc --noEmit",
"with-env": "dotenvx run --convention=nextjs -fk ../../.env.keys --",
"with-env": "../../packages/scripts/bin/env.sh",
"ui-add": "pnpm dlx shadcn@latest add --overwrite && biome format src --write",
"storybook:todo": "storybook dev -p 6006",
"storybook": "echo \"TODO put mue back \"",
Expand All @@ -24,7 +24,6 @@
"@acme/tailwind-config": "workspace:*",
"@acme/ui": "workspace:*",
"@acme/validators": "workspace:*",
"@dotenvx/dotenvx": "^1.51.0",
"@expo/next-adapter": "^6.0.0",
"@hookform/resolvers": "^5.2.2",
"@radix-ui/react-avatar": "^1.1.10",
Expand Down
29 changes: 22 additions & 7 deletions apps/nextjs/start.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,34 @@ fi

# Production mode

if [ -z "$DOTENV_PRIVATE_KEY_PRODUCTION" ]; then
echo "Error: DOTENV_PRIVATE_KEY_PRODUCTION is not set."
exit 1
# Load environment variables
ENV_FILE="/app/.env.production"
ENV_SOPS_FILE="/app/.env.production.sops"

if [ -f "$ENV_SOPS_FILE" ] && command -v sops >/dev/null 2>&1; then
echo "Decrypting env from $ENV_SOPS_FILE"
tmp_env="$(mktemp)"
trap 'rm -f "$tmp_env"' EXIT
sops -d "$ENV_SOPS_FILE" > "$tmp_env"
set -a
# shellcheck disable=SC1090
. "$tmp_env"
set +a
elif [ -f "$ENV_FILE" ]; then
echo "Loading env from $ENV_FILE"
set -a
# shellcheck disable=SC1090
. "$ENV_FILE"
set +a
else
echo "DOTENV_PRIVATE_KEY_PRODUCTION is set."
echo "No production env file found; proceeding with existing environment"
fi

# Run db migration
cd /app/packages/db
dotenvx run -f /app/.env.production --ignore=MISSING_ENV_FILE -- \
npx -p @neondatabase/serverless -p drizzle-orm -p drizzle-kit drizzle-kit migrate
NODE_ENV=production npx -p @neondatabase/serverless -p drizzle-orm -p drizzle-kit drizzle-kit migrate
cd /app

# Start the Next.js application
echo "Starting in production mode..."
dotenvx run -f .env.production --ignore=MISSING_ENV_FILE -- node /app/server.js -H 0.0.0.0
node /app/server.js -H 0.0.0.0
5 changes: 3 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ services:
- "3000:3000"
volumes:
- ./apps/nextjs:/app
# dont put it in /app or it will create a copy of the .env.keys file in host
- ./.env.keys:/.env.keys
# Optional: mount SOPS age key for local dev (do not commit)
- ./age.key:/age.key:ro
# exclusions
# - /app/.venv
environment:
- NODE_ENV=development
- ENV=development
- SOPS_AGE_KEY_FILE=/age.key
- POSTGRES_URL=postgresql://pguser:password@postgres:5432/app
- REDIS_URL=redis://redis:6379
depends_on:
Expand Down
2 changes: 1 addition & 1 deletion packages/scripts/bin/deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,4 @@ fly deploy \
-a "${APPNAME}" \
-c "${APPDIR}/fly-${2}.toml" \
--dockerfile "scripts/docker/${1}.Dockerfile" \
--build-arg "$KEYNAME=$(dotenvx keypair $KEYNAME -f .env.${2})"
--build-arg "$KEYNAME=$(printenv "$KEYNAME")"
Loading
Loading