-
-
Save mpociot/1d6809a600701beca4fa544551acd2de to your computer and use it in GitHub Desktop.
/bin/bash -c "$(curl -fsSL https://php.new/install/linux)" | |
export PATH="/root/.config/herd-lite/bin/:$PATH" | |
composer install | |
cp .env.example .env | |
php artisan key:generate | |
php artisan migrate --seed --force -n | |
npm install | |
npm run build |
here is the version with MySQL IT WORKS
link to the original article:
https://dev.to/javiereguiluz/how-to-make-chatgpt-codex-work-with-php-and-symfony-4lj8
I've created a script here that uses
- MySQL
- Meilisearch
- Yarn (Instead of NPM)
Codex Environment Settings:
- Agent internet access => Off
- Image => universal
- Secrets => None
- Environment variables => None
Here the script
#!/usr/bin/env bash
# Fail fast, fail loud.
set -euo pipefail
################################################################################
# 1. PHP & Composer ############################################################
################################################################################
add-apt-repository -y ppa:ondrej/php
apt-get update
apt-get install -y \
php8.4 php8.4-cli php8.4-mbstring php8.4-xml php8.4-intl \
php8.4-gd php8.4-zip php8.4-curl php8.4-mysql \
curl gnupg lsb-release ca-certificates
update-alternatives --install /usr/bin/php php /usr/bin/php8.4 84
update-alternatives --set php /usr/bin/php8.4
EXPECTED_CHECKSUM="$(curl -fsSL https://composer.github.io/installer.sig)"
curl -fsSL https://getcomposer.org/installer -o composer-setup.php
ACTUAL_CHECKSUM="$(sha384sum composer-setup.php | cut -d ' ' -f 1)"
[ "$EXPECTED_CHECKSUM" = "$ACTUAL_CHECKSUM" ] || { echo "Composer installer corrupt" >&2; exit 1; }
php composer-setup.php --install-dir=/usr/local/bin --filename=composer --quiet
rm composer-setup.php
composer install --ignore-platform-req=ext-bcmath
php -v; composer -V
################################################################################
# 2. Node.js & Yarn ############################################################
################################################################################
NODE_VERSION="${NODE_VERSION:-20}"
YARN_VERSION="${YARN_VERSION:-1.22.22}"
# Install the desired Node LTS via NodeSource
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
apt-get install -y nodejs
# ---------------------------------------------------------------------------
# Yarn (via Corepack)
# ---------------------------------------------------------------------------
# Node ≥16 ships with Corepack, which can activate pinned versions of Yarn.
# This avoids npm‑global install conflicts and sticks to a reproducible version.
if ! command -v corepack >/dev/null 2>&1; then
# Fallback for odd Node builds that omit Corepack
npm install -g corepack
fi
corepack enable
corepack prepare "yarn@${YARN_VERSION}" --activate
node -v; yarn -v
################################################################################
# 3. MySQL (local, socket‑based) ###############################################
################################################################################
DB_DATABASE="${DB_DATABASE:-mydb}"
DB_USERNAME="${DB_USERNAME:-myuser}"
DB_PASSWORD="${DB_PASSWORD:-mypassword}"
export DB_CONNECTION=mysql
export DB_HOST=127.0.0.1
export DB_PORT=3306
export DB_DATABASE DB_USERNAME DB_PASSWORD
apt-get install -y mysql-client mysql-common mysql-server-core-8.0
MYSQL_DATADIR="/tmp/mysql-data"; MYSQL_SOCKET="/tmp/mysql.sock"
mkdir -p "$MYSQL_DATADIR"
mysqld --initialize-insecure --datadir="$MYSQL_DATADIR"
mkdir -p /var/lib/mysql-files
nohup mysqld --user=root --datadir="$MYSQL_DATADIR" --socket="$MYSQL_SOCKET" \
> /tmp/mysql.log 2>&1 &
printf "Waiting for MySQL"; for _ in {30..0}; do
if mysqladmin --socket="$MYSQL_SOCKET" ping --silent 2>/dev/null; then
echo -e "\r✅ MySQL ready "; break; fi
printf "."; sleep 1; done
mysqladmin --socket="$MYSQL_SOCKET" ping --silent >/dev/null || { tail -n 50 /tmp/mysql.log; exit 1; }
mysql -u root --socket="$MYSQL_SOCKET" <<SQL
CREATE DATABASE IF NOT EXISTS \`$DB_DATABASE\`;
CREATE USER IF NOT EXISTS '$DB_USERNAME'@'%' IDENTIFIED BY '$DB_PASSWORD';
GRANT ALL PRIVILEGES ON \`$DB_DATABASE\`.* TO '$DB_USERNAME'@'%';
FLUSH PRIVILEGES;
SQL
mysql --version
################################################################################
# 4. Meilisearch (needed by seeders) ###########################################
################################################################################
MEILI_VERSION="${MEILI_VERSION:-latest}"
MEILI_MASTER_KEY="${MEILI_MASTER_KEY:-masterKey}"
MEILISEARCH_BIN="/usr/local/bin/meilisearch"
MEILISEARCH_HOST="http://127.0.0.1:7700"
if [ ! -x "$MEILISEARCH_BIN" ]; then
echo "Installing Meilisearch ($MEILI_VERSION) …"
if [ "$MEILI_VERSION" = "latest" ]; then
curl -L https://install.meilisearch.com | sh
else
ASSET_URL="https://github.com/meilisearch/meilisearch/releases/download/${MEILI_VERSION}/meilisearch-linux-amd64"
if ! curl -fSL "$ASSET_URL" -o meilisearch; then
echo "⚠️ Version $MEILI_VERSION not found – falling back to latest" >&2
curl -L https://install.meilisearch.com | sh
fi
fi
chmod +x ./meilisearch
mv ./meilisearch "$MEILISEARCH_BIN"
fi
export MEILISEARCH_HOST MEILISEARCH_KEY="$MEILI_MASTER_KEY"
nohup "$MEILISEARCH_BIN" --master-key "$MEILI_MASTER_KEY" --http-addr "127.0.0.1:7700" \
> /tmp/meilisearch.log 2>&1 &
printf "Waiting for Meilisearch"; for _ in {30..0}; do
if curl -sf "$MEILISEARCH_HOST/health" >/dev/null; then
echo -e "\r✅ Meilisearch healthy "; break; fi
printf "."; sleep 1; done
curl -sf "$MEILISEARCH_HOST/health" >/dev/null || { echo; tail -n 50 /tmp/meilisearch.log; exit 1; }
################################################################################
# 5. Build the Laravel application ############################################
################################################################################
cp .env.example .env
update_env() {
local key="$1"
local value="$2"
# Escape replacement string for sed (handles /, \ and &)
local escaped_value
escaped_value=$(printf '%s' "$value" | sed -e 's/[\\/&]/\\&/g')
if grep -q "^$key=" .env; then
sed -i "s|^$key=.*|$key=$escaped_value|" .env
else
echo "$key=$value" >> .env
fi
}
update_env DB_HOST 127.0.0.1
update_env DB_DATABASE "$DB_DATABASE"
update_env DB_USERNAME "$DB_USERNAME"
update_env DB_PASSWORD "$DB_PASSWORD"
update_env MEILISEARCH_HOST "$MEILISEARCH_HOST"
update_env MEILISEARCH_KEY "$MEILI_MASTER_KEY"
php artisan key:generate
php artisan migrate --seed --force -n
# JavaScript dependencies & build (Yarn Classic tolerates peer conflicts)
yarn install --non-interactive --no-progress
yarn run build
################################################################################
# Done #########################################################################
################################################################################
I've created a script here that uses
- MySQL
- Meilisearch
- Yarn (Instead of NPM)
Codex Environment Settings:
- Agent internet access => Off
- Image => universal
- Secrets => None
- Environment variables => None
Here the script
#!/usr/bin/env bash # Fail fast, fail loud. set -euo pipefail ################################################################################ # 1. PHP & Composer ############################################################ ################################################################################ add-apt-repository -y ppa:ondrej/php apt-get update apt-get install -y \ php8.4 php8.4-cli php8.4-mbstring php8.4-xml php8.4-intl \ php8.4-gd php8.4-zip php8.4-curl php8.4-mysql \ curl gnupg lsb-release ca-certificates update-alternatives --install /usr/bin/php php /usr/bin/php8.4 84 update-alternatives --set php /usr/bin/php8.4 EXPECTED_CHECKSUM="$(curl -fsSL https://composer.github.io/installer.sig)" curl -fsSL https://getcomposer.org/installer -o composer-setup.php ACTUAL_CHECKSUM="$(sha384sum composer-setup.php | cut -d ' ' -f 1)" [ "$EXPECTED_CHECKSUM" = "$ACTUAL_CHECKSUM" ] || { echo "Composer installer corrupt" >&2; exit 1; } php composer-setup.php --install-dir=/usr/local/bin --filename=composer --quiet rm composer-setup.php composer install --ignore-platform-req=ext-bcmath php -v; composer -V ################################################################################ # 2. Node.js & Yarn ############################################################ ################################################################################ NODE_VERSION="${NODE_VERSION:-20}" YARN_VERSION="${YARN_VERSION:-1.22.22}" # Install the desired Node LTS via NodeSource curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash - apt-get install -y nodejs # --------------------------------------------------------------------------- # Yarn (via Corepack) # --------------------------------------------------------------------------- # Node ≥16 ships with Corepack, which can activate pinned versions of Yarn. # This avoids npm‑global install conflicts and sticks to a reproducible version. if ! command -v corepack >/dev/null 2>&1; then # Fallback for odd Node builds that omit Corepack npm install -g corepack fi corepack enable corepack prepare "yarn@${YARN_VERSION}" --activate node -v; yarn -v ################################################################################ # 3. MySQL (local, socket‑based) ############################################### ################################################################################ DB_DATABASE="${DB_DATABASE:-mydb}" DB_USERNAME="${DB_USERNAME:-myuser}" DB_PASSWORD="${DB_PASSWORD:-mypassword}" export DB_CONNECTION=mysql export DB_HOST=127.0.0.1 export DB_PORT=3306 export DB_DATABASE DB_USERNAME DB_PASSWORD apt-get install -y mysql-client mysql-common mysql-server-core-8.0 MYSQL_DATADIR="/tmp/mysql-data"; MYSQL_SOCKET="/tmp/mysql.sock" mkdir -p "$MYSQL_DATADIR" mysqld --initialize-insecure --datadir="$MYSQL_DATADIR" mkdir -p /var/lib/mysql-files nohup mysqld --user=root --datadir="$MYSQL_DATADIR" --socket="$MYSQL_SOCKET" \ > /tmp/mysql.log 2>&1 & printf "Waiting for MySQL"; for _ in {30..0}; do if mysqladmin --socket="$MYSQL_SOCKET" ping --silent 2>/dev/null; then echo -e "\r✅ MySQL ready "; break; fi printf "."; sleep 1; done mysqladmin --socket="$MYSQL_SOCKET" ping --silent >/dev/null || { tail -n 50 /tmp/mysql.log; exit 1; } mysql -u root --socket="$MYSQL_SOCKET" <<SQL CREATE DATABASE IF NOT EXISTS \`$DB_DATABASE\`; CREATE USER IF NOT EXISTS '$DB_USERNAME'@'%' IDENTIFIED BY '$DB_PASSWORD'; GRANT ALL PRIVILEGES ON \`$DB_DATABASE\`.* TO '$DB_USERNAME'@'%'; FLUSH PRIVILEGES; SQL mysql --version ################################################################################ # 4. Meilisearch (needed by seeders) ########################################### ################################################################################ MEILI_VERSION="${MEILI_VERSION:-latest}" MEILI_MASTER_KEY="${MEILI_MASTER_KEY:-masterKey}" MEILISEARCH_BIN="/usr/local/bin/meilisearch" MEILISEARCH_HOST="http://127.0.0.1:7700" if [ ! -x "$MEILISEARCH_BIN" ]; then echo "Installing Meilisearch ($MEILI_VERSION) …" if [ "$MEILI_VERSION" = "latest" ]; then curl -L https://install.meilisearch.com | sh else ASSET_URL="https://github.com/meilisearch/meilisearch/releases/download/${MEILI_VERSION}/meilisearch-linux-amd64" if ! curl -fSL "$ASSET_URL" -o meilisearch; then echo "⚠️ Version $MEILI_VERSION not found – falling back to latest" >&2 curl -L https://install.meilisearch.com | sh fi fi chmod +x ./meilisearch mv ./meilisearch "$MEILISEARCH_BIN" fi export MEILISEARCH_HOST MEILISEARCH_KEY="$MEILI_MASTER_KEY" nohup "$MEILISEARCH_BIN" --master-key "$MEILI_MASTER_KEY" --http-addr "127.0.0.1:7700" \ > /tmp/meilisearch.log 2>&1 & printf "Waiting for Meilisearch"; for _ in {30..0}; do if curl -sf "$MEILISEARCH_HOST/health" >/dev/null; then echo -e "\r✅ Meilisearch healthy "; break; fi printf "."; sleep 1; done curl -sf "$MEILISEARCH_HOST/health" >/dev/null || { echo; tail -n 50 /tmp/meilisearch.log; exit 1; } ################################################################################ # 5. Build the Laravel application ############################################ ################################################################################ cp .env.example .env update_env() { local key="$1" local value="$2" # Escape replacement string for sed (handles /, \ and &) local escaped_value escaped_value=$(printf '%s' "$value" | sed -e 's/[\\/&]/\\&/g') if grep -q "^$key=" .env; then sed -i "s|^$key=.*|$key=$escaped_value|" .env else echo "$key=$value" >> .env fi } update_env DB_HOST 127.0.0.1 update_env DB_DATABASE "$DB_DATABASE" update_env DB_USERNAME "$DB_USERNAME" update_env DB_PASSWORD "$DB_PASSWORD" update_env MEILISEARCH_HOST "$MEILISEARCH_HOST" update_env MEILISEARCH_KEY "$MEILI_MASTER_KEY" php artisan key:generate php artisan migrate --seed --force -n # JavaScript dependencies & build (Yarn Classic tolerates peer conflicts) yarn install --non-interactive --no-progress yarn run build ################################################################################ # Done ######################################################################### ################################################################################
Here's a smaller version which pulls from my Gist's.
#!/usr/bin/env bash
###############################################################################
# Codex Laravel: lightweight orchestrator ######################################
###############################################################################
# This tiny entry‑point just stitches together a handful of *modular* scripts
# you now keep in public GitHub gists. Each gist handles one concern (PHP/Composer,
# Yarn/Node, MySQL, Meilisearch). The big upside is that you can iterate on any
# of those pieces in isolation without touching this file.
###############################################################################
set -euo pipefail
###############################################################################
# 0. Defaults & env ...........................................................
###############################################################################
# -----------------------------------------------------------------------------
# Database credentials (used by both MySQL & Laravel)
# -----------------------------------------------------------------------------
DB_DATABASE="${DB_DATABASE:-mydb}"
DB_USERNAME="${DB_USERNAME:-myuser}"
DB_PASSWORD="${DB_PASSWORD:-mypassword}"
export DB_DATABASE DB_USERNAME DB_PASSWORD
# -----------------------------------------------------------------------------
# Node/Yarn versions (used by the Yarn setup gist)
# -----------------------------------------------------------------------------
NODE_VERSION="${NODE_VERSION:-20}"
YARN_VERSION="${YARN_VERSION:-1.22.22}"
export NODE_VERSION YARN_VERSION
# -----------------------------------------------------------------------------
# Meilisearch versions / credentials
# -----------------------------------------------------------------------------
MEILI_VERSION="${MEILI_VERSION:-latest}"
MEILI_MASTER_KEY="${MEILI_MASTER_KEY:-masterKey}"
export MEILI_VERSION MEILI_MASTER_KEY
###############################################################################
# Helper – download & execute a gist ..........................................
###############################################################################
run_gist() {
local raw_url="$1"
echo -e "\n🔽 Running remote gist: $raw_url\n"
curl -fsSL "$raw_url" | bash -s --
}
###############################################################################
# 1. PHP & Composer ............................................................
###############################################################################
run_gist "https://gist.githubusercontent.com/AniTexs/63c116ccbabc78831fd45ad94398bfa3/raw"
###############################################################################
# 2. Node.js & Yarn ............................................................
###############################################################################
run_gist "https://gist.githubusercontent.com/AniTexs/5a31efa79f6b5708449a3067cd12d25a/raw"
###############################################################################
# 3. MySQL (local) .............................................................
###############################################################################
run_gist "https://gist.githubusercontent.com/AniTexs/10ce4272a96763c53c4e46bfbd91c49c/raw"
###############################################################################
# 4. Meilisearch ...............................................................
###############################################################################
run_gist "https://gist.githubusercontent.com/AniTexs/99e66d818a21cdce70c6c0f3f256c99a/raw"
###############################################################################
# 5. Build Laravel app ........................................................
###############################################################################
# -- .env ----------------------------------------------------------------------
cp .env.example .env
update_env() {
local key="$1"; local value="$2"
local escaped_value
escaped_value=$(printf '%s' "$value" | sed -e 's/[\\/&]/\\&/g')
if grep -q "^$key=" .env; then
sed -i "s|^$key=.*|$key=$escaped_value|" .env
else
echo "$key=$value" >> .env
fi
}
update_env DB_HOST 127.0.0.1
update_env DB_DATABASE "$DB_DATABASE"
update_env DB_USERNAME "$DB_USERNAME"
update_env DB_PASSWORD "$DB_PASSWORD"
update_env MEILISEARCH_HOST "http://127.0.0.1:7700"
update_env MEILISEARCH_KEY "$MEILI_MASTER_KEY"
# -- Laravel -------------------------------------------------------------------
php artisan key:generate
php artisan migrate --seed --force -n
# -- JavaScript deps & build ----------------------------------------------------
yarn install --non-interactive --no-progress
yarn run build
###############################################################################
# Done #########################################################################
###############################################################################
how are these scripts used in the context of https://chatgpt.com/codex
?
I mean, how do I make the environment where Codex is running to execute these commands? My best guess here is to indicate it in an AGENTS.md file and keep this codex.sh
script somewhere else?
Thanks!
how are these scripts used in the context of
https://chatgpt.com/codex
?I mean, how do I make the environment where Codex is running to execute these commands? My best guess here is to indicate it in an AGENTS.md file and keep this
codex.sh
script somewhere else?Thanks!
in the web version of codex (which where you use this)
you create an environment at chatgpt.com/codex, and go to its setup configuration. there will be a textarea where you can a write a setup script for the environment. that’s where this goes.
refer to https://dev.to/javiereguiluz/how-to-make-chatgpt-codex-work-with-php-and-symfony-4lj8
here is the version with MySQL
IT WORKS
`#!/usr/bin/env bash
this makes the script strict:
-e: exit on any error
-u: error on undefined variables
-o pipefail: exit if any command in a pipeline fails
set -euo pipefail
Adds a package repository that provides the latest PHP versions
(see https://deb.sury.org/ for details)
add-apt-repository -y ppa:ondrej/php
Updates package lists to get the latest information about available packages
apt-get update
Install PHP 8.4 and extensions commonly needed for Symfony applications
apt-get install -y
php8.4
php8.4-cli
php8.4-mbstring
php8.4-xml
php8.4-intl
php8.4-gd
php8.4-zip
php8.4-curl
php8.4-mysql # ✅ Also switch from pgsql to mysql now
This makes PHP 8.4 available through the global 'php' binary,
which is expected by many commands
update-alternatives --install /usr/bin/php php /usr/bin/php8.4 84
update-alternatives --set php /usr/bin/php8.4
Install Composer as a global 'composer' binary following the safest practices
EXPECTED_CHECKSUM="$(curl -fsSL https://composer.github.io/installer.sig)"
curl -fsSL https://getcomposer.org/installer -o composer-setup.php
ACTUAL_CHECKSUM="$(sha384sum composer-setup.php | cut -d ' ' -f 1)"
if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]; then
echo 'ERROR: Invalid composer installer checksum.' >&2
rm composer-setup.php
exit 1
fi
php composer-setup.php --install-dir=/usr/local/bin --filename=composer --quiet
rm composer-setup.php
Install the PHP dependencies of your project;
private packages require some more work explained later in this article
composer install --ignore-platform-req=ext-bcmath
Show installed versions to check if everything worked
php -v
composer --version
Load Laravel-style environment variables
DB_DATABASE="${DB_DATABASE:-mydb}"
DB_USERNAME="${DB_USERNAME:-myuser}"
DB_PASSWORD="${DB_PASSWORD:-mypassword}"
Default MySQL root password (optional, can be customized)
MYSQL_ROOT_PASSWORD="${MYSQL_ROOT_PASSWORD:-root}"
apt-get install -y mysql-client mysql-common mysql-server-core-8.0
mkdir -p /tmp/mysql-data
mysqld --initialize-insecure --datadir=/tmp/mysql-data
Fix for secure-file-priv error
mkdir -p /var/lib/mysql-files
Start MySQL manually
nohup mysqld --user=root --datadir=/tmp/mysql-data --socket=/tmp/mysql.sock > /tmp/mysql.log 2>&1 &
Wait for socket
echo "Waiting for MySQL to be ready..."
for i in {30..0}; do
if [ -S /tmp/mysql.sock ]; then
echo "✅ MySQL socket is ready"
break
fi
sleep 1
done
if ! [ -S /tmp/mysql.sock ]; then
echo "❌ MySQL failed to start"
tail -n 50 /tmp/mysql.log || true
exit 1
fi
Setup user/db
mysql -u root --socket=/tmp/mysql.sock <<-EOSQL
CREATE DATABASE IF NOT EXISTS `${DB_DATABASE}`;
CREATE USER IF NOT EXISTS '${DB_USERNAME}'@'localhost' IDENTIFIED BY '${DB_PASSWORD}';
GRANT ALL PRIVILEGES ON `${DB_DATABASE}`.* TO '${DB_USERNAME}'@'localhost';
FLUSH PRIVILEGES;
EOSQL
Show installed MySQL version
mysql --version
cp .env.example .env
php artisan key:generate
php artisan migrate --seed --force -n
npm install --no-save
npm run build`