From 0e6f5492b556ce862cdb231407026bb8eabce3f9 Mon Sep 17 00:00:00 2001
From: Wilmer Arambula
Date: Wed, 3 Sep 2025 05:04:10 -0400
Subject: [PATCH 1/5] feature(app): Implement `Nginx` stack.
---
.github/workflows/build.yml | 36 ++++++---
CHANGELOG.md | 1 +
codeception.yml | 1 -
composer.lock | 92 +++++++++++------------
docker-compose.yml | 30 ++++++++
docker/entrypoint.sh | 14 ++++
docker/init.sh | 101 ++++++++++++++++++++++++++
docker/nginx/Dockerfile | 60 +++++++++++++++
docker/nginx/default.conf | 94 ++++++++++++++++++++++++
docker/nginx/nginx.conf | 58 +++++++++++++++
docker/php/php.ini | 23 ++++++
docker/ssl/localhost-key.pem | 28 +++++++
docker/ssl/localhost.pem | 26 +++++++
docker/supervisor/conf.d/nginx.conf | 12 +++
docker/supervisor/conf.d/php-fpm.conf | 13 ++++
docker/supervisor/conf.d/queue.conf | 11 +++
docker/supervisor/supervisord.conf | 14 ++++
tests/Acceptance.suite.yml | 2 +-
tests/_envs/dockerized.yml | 4 -
tests/_envs/php-builtin.yml | 9 ---
20 files changed, 557 insertions(+), 72 deletions(-)
create mode 100644 docker-compose.yml
create mode 100644 docker/entrypoint.sh
create mode 100644 docker/init.sh
create mode 100644 docker/nginx/Dockerfile
create mode 100644 docker/nginx/default.conf
create mode 100644 docker/nginx/nginx.conf
create mode 100644 docker/php/php.ini
create mode 100644 docker/ssl/localhost-key.pem
create mode 100644 docker/ssl/localhost.pem
create mode 100644 docker/supervisor/conf.d/nginx.conf
create mode 100644 docker/supervisor/conf.d/php-fpm.conf
create mode 100644 docker/supervisor/conf.d/queue.conf
create mode 100644 docker/supervisor/supervisord.conf
delete mode 100644 tests/_envs/dockerized.yml
delete mode 100644 tests/_envs/php-builtin.yml
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0c908e6..6240e0f 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -18,12 +18,30 @@ on:
name: build
jobs:
- codeception:
- uses: php-forge/actions/.github/workflows/codeception.yml@main
- secrets:
- AUTH_TOKEN: ${{ secrets.AUTH_TOKEN }}
- CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
- with:
- codeception-command: vendor/bin/codecept run --env php-builtin --coverage-xml
- coverage-file: runtime/output/coverage.xml
- extensions: gd, intl, pcov
+ nginx:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout.
+ uses: actions/checkout@v5
+
+ - name: Install docker compose.
+ run: |
+ sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
+ sudo chmod +x /usr/local/bin/docker-compose
+ docker-compose --version
+
+ - name: Build and start containers.
+ run: docker-compose up -d --build
+
+ - name: Wait for container to be ready.
+ run: |
+ echo "Waiting 30 seconds for container initialization..."
+ sleep 30
+ docker logs yii2-apache
+
+ - name: Codeceptcion build.
+ run: docker exec yii2-apache vendor/bin/codecept build
+
+ - name: Run codeception tests.
+ run: docker exec yii2-apache vendor/bin/codecept run
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dec76f..de70100 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
- Bug #172: Update badge label from `PHPUnit` to `Codeception` in `README.md` (@terabytesoftw)
- Bug #175: Update allowed IPs in configuration for development purposes in `configuration.md` (@terabytesoftw)
- Bug #177: Add missing config path to ECS configuration in `ecs.php` (@terabytesoftw)
+- Enh #181: Implement `Nginx` stack (@terabytesoftw)
## 0.1.0 August 31, 2025
diff --git a/codeception.yml b/codeception.yml
index 9c300d2..bb00d71 100644
--- a/codeception.yml
+++ b/codeception.yml
@@ -6,7 +6,6 @@ paths:
output: runtime/output
data: tests/Support/data
support: tests/Support
- envs: tests/_envs
actor_suffix: Tester
settings:
memory_limit: 1024M
diff --git a/composer.lock b/composer.lock
index 49a6f96..f78b6ed 100644
--- a/composer.lock
+++ b/composer.lock
@@ -77,12 +77,12 @@
"source": {
"type": "git",
"url": "https://github.com/composer/ca-bundle.git",
- "reference": "719026bb30813accb68271fee7e39552a58e9f65"
+ "reference": "40f256d6df5e9fab5618583f81b105d2e4143249"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/ca-bundle/zipball/719026bb30813accb68271fee7e39552a58e9f65",
- "reference": "719026bb30813accb68271fee7e39552a58e9f65",
+ "url": "https://api.github.com/repos/composer/ca-bundle/zipball/40f256d6df5e9fab5618583f81b105d2e4143249",
+ "reference": "40f256d6df5e9fab5618583f81b105d2e4143249",
"shasum": ""
},
"require": {
@@ -130,7 +130,7 @@
"support": {
"irc": "irc://irc.freenode.org/composer",
"issues": "https://github.com/composer/ca-bundle/issues",
- "source": "https://github.com/composer/ca-bundle/tree/1.5.8"
+ "source": "https://github.com/composer/ca-bundle/tree/main"
},
"funding": [
{
@@ -142,7 +142,7 @@
"type": "github"
}
],
- "time": "2025-08-20T18:49:47+00:00"
+ "time": "2025-09-03T07:43:57+00:00"
},
{
"name": "composer/class-map-generator",
@@ -220,12 +220,12 @@
"source": {
"type": "git",
"url": "https://github.com/composer/composer.git",
- "reference": "b88968cf6ad5098de2d5510e42216c4d912940cc"
+ "reference": "a9226c2c08f641720390f5750229c730fa4e1b83"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/composer/zipball/b88968cf6ad5098de2d5510e42216c4d912940cc",
- "reference": "b88968cf6ad5098de2d5510e42216c4d912940cc",
+ "url": "https://api.github.com/repos/composer/composer/zipball/a9226c2c08f641720390f5750229c730fa4e1b83",
+ "reference": "a9226c2c08f641720390f5750229c730fa4e1b83",
"shasum": ""
},
"require": {
@@ -323,7 +323,7 @@
"type": "github"
}
],
- "time": "2025-08-27T20:54:37+00:00"
+ "time": "2025-09-03T07:33:19+00:00"
},
{
"name": "composer/metadata-minifier",
@@ -331,12 +331,12 @@
"source": {
"type": "git",
"url": "https://github.com/composer/metadata-minifier.git",
- "reference": "0a38292ff395f3716454613e3a6c6eaa422456c8"
+ "reference": "9178fb630c1f69cb0f3b56e2052ed3d347fa171a"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/0a38292ff395f3716454613e3a6c6eaa422456c8",
- "reference": "0a38292ff395f3716454613e3a6c6eaa422456c8",
+ "url": "https://api.github.com/repos/composer/metadata-minifier/zipball/9178fb630c1f69cb0f3b56e2052ed3d347fa171a",
+ "reference": "9178fb630c1f69cb0f3b56e2052ed3d347fa171a",
"shasum": ""
},
"require": {
@@ -387,13 +387,9 @@
{
"url": "https://github.com/composer",
"type": "github"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/composer/composer",
- "type": "tidelift"
}
],
- "time": "2025-02-17T12:51:19+00:00"
+ "time": "2025-09-03T06:59:18+00:00"
},
{
"name": "composer/pcre",
@@ -478,12 +474,12 @@
"source": {
"type": "git",
"url": "https://github.com/composer/semver.git",
- "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95"
+ "reference": "b52829022cb18210bb84e44e457bd4e890f8d2a7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/composer/semver/zipball/198166618906cb2de69b95d7d47e5fa8aa1b2b95",
- "reference": "198166618906cb2de69b95d7d47e5fa8aa1b2b95",
+ "url": "https://api.github.com/repos/composer/semver/zipball/b52829022cb18210bb84e44e457bd4e890f8d2a7",
+ "reference": "b52829022cb18210bb84e44e457bd4e890f8d2a7",
"shasum": ""
},
"require": {
@@ -536,7 +532,7 @@
"support": {
"irc": "ircs://irc.libera.chat:6697/composer",
"issues": "https://github.com/composer/semver/issues",
- "source": "https://github.com/composer/semver/tree/3.4.4"
+ "source": "https://github.com/composer/semver/tree/main"
},
"funding": [
{
@@ -548,7 +544,7 @@
"type": "github"
}
],
- "time": "2025-08-20T19:15:30+00:00"
+ "time": "2025-09-03T06:59:12+00:00"
},
{
"name": "composer/spdx-licenses",
@@ -1573,12 +1569,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
- "reference": "dc8d57e6d71f26f368f80053b4e5bc92f6c395e5"
+ "reference": "cd6aabaab6fb2bf642488d3f769adf24569e329e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/console/zipball/dc8d57e6d71f26f368f80053b4e5bc92f6c395e5",
- "reference": "dc8d57e6d71f26f368f80053b4e5bc92f6c395e5",
+ "url": "https://api.github.com/repos/symfony/console/zipball/cd6aabaab6fb2bf642488d3f769adf24569e329e",
+ "reference": "cd6aabaab6fb2bf642488d3f769adf24569e329e",
"shasum": ""
},
"require": {
@@ -1663,7 +1659,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-29T07:40:56+00:00"
+ "time": "2025-09-01T13:42:51+00:00"
},
{
"name": "symfony/deprecation-contracts",
@@ -2775,12 +2771,12 @@
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
- "reference": "b87a95c24475492ac665704843e341873eea1b28"
+ "reference": "3bd28ceb20216559209766b2ad3154d7d9f3254d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/string/zipball/b87a95c24475492ac665704843e341873eea1b28",
- "reference": "b87a95c24475492ac665704843e341873eea1b28",
+ "url": "https://api.github.com/repos/symfony/string/zipball/3bd28ceb20216559209766b2ad3154d7d9f3254d",
+ "reference": "3bd28ceb20216559209766b2ad3154d7d9f3254d",
"shasum": ""
},
"require": {
@@ -2858,7 +2854,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-26T09:23:28+00:00"
+ "time": "2025-09-01T09:26:06+00:00"
},
{
"name": "ui-awesome/html-attribute",
@@ -5373,12 +5369,12 @@
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "b3ae3d27beb3625f29c7a01799d3f45506c53745"
+ "reference": "e0c4844a5a3cc0b7f18861d2121b22fe731bce2d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/b3ae3d27beb3625f29c7a01799d3f45506c53745",
- "reference": "b3ae3d27beb3625f29c7a01799d3f45506c53745",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e0c4844a5a3cc0b7f18861d2121b22fe731bce2d",
+ "reference": "e0c4844a5a3cc0b7f18861d2121b22fe731bce2d",
"shasum": ""
},
"require": {
@@ -5424,7 +5420,7 @@
"type": "github"
}
],
- "time": "2025-08-31T15:28:24+00:00"
+ "time": "2025-09-02T16:58:05+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
@@ -5432,12 +5428,12 @@
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
- "reference": "b043bd81404b8e4e4783c8b348c05bc08fafeb02"
+ "reference": "e8616380171ea0b85a98d3dabbbf9cfdc461f47d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/b043bd81404b8e4e4783c8b348c05bc08fafeb02",
- "reference": "b043bd81404b8e4e4783c8b348c05bc08fafeb02",
+ "url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/e8616380171ea0b85a98d3dabbbf9cfdc461f47d",
+ "reference": "e8616380171ea0b85a98d3dabbbf9cfdc461f47d",
"shasum": ""
},
"require": {
@@ -5473,7 +5469,7 @@
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.x"
},
- "time": "2025-08-30T08:29:42+00:00"
+ "time": "2025-09-01T15:58:43+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -5481,12 +5477,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "96dc0466673e215bf5536301039017f03cd45c6b"
+ "reference": "da2cdaff87220fa641e7652364281b736e4347e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/96dc0466673e215bf5536301039017f03cd45c6b",
- "reference": "96dc0466673e215bf5536301039017f03cd45c6b",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/da2cdaff87220fa641e7652364281b736e4347e0",
+ "reference": "da2cdaff87220fa641e7652364281b736e4347e0",
"shasum": ""
},
"require": {
@@ -5543,7 +5539,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.5"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/12.3.6"
},
"funding": [
{
@@ -5563,7 +5559,7 @@
"type": "tidelift"
}
],
- "time": "2025-09-01T08:07:42+00:00"
+ "time": "2025-09-02T05:23:14+00:00"
},
{
"name": "phpunit/php-file-iterator",
@@ -5868,12 +5864,12 @@
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "fb9037c729d0298d9052e92303a8bd4213659116"
+ "reference": "864e93c73b6e4caf189461cdbdf63853c54271e2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fb9037c729d0298d9052e92303a8bd4213659116",
- "reference": "fb9037c729d0298d9052e92303a8bd4213659116",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/864e93c73b6e4caf189461cdbdf63853c54271e2",
+ "reference": "864e93c73b6e4caf189461cdbdf63853c54271e2",
"shasum": ""
},
"require": {
@@ -5887,7 +5883,7 @@
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.3",
- "phpunit/php-code-coverage": "^12.3.4",
+ "phpunit/php-code-coverage": "^12.3.6",
"phpunit/php-file-iterator": "^6.0.0",
"phpunit/php-invoker": "^6.0.0",
"phpunit/php-text-template": "^5.0.0",
@@ -5966,7 +5962,7 @@
"type": "tidelift"
}
],
- "time": "2025-08-29T11:33:58+00:00"
+ "time": "2025-09-03T06:27:18+00:00"
},
{
"name": "psr/event-dispatcher",
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..8049ddc
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,30 @@
+services:
+ yii2-nginx:
+ build:
+ args:
+ USER_ID: ${USER_ID:-1000}
+ GROUP_ID: ${GROUP_ID:-1000}
+ USER_NAME: ${USER_NAME:-www-data}
+ GROUP_NAME: ${GROUP_NAME:-www-data}
+ context: .
+ dockerfile: docker/nginx/Dockerfile
+ container_name: yii2-nginx
+ entrypoint: ["/usr/local/bin/entrypoint.sh"]
+ env_file:
+ - .env
+ environment:
+ TZ: "UTC"
+ YII_DEBUG: "${YII_DEBUG:-false}"
+ YII_ENV: "${YII_ENV:-prod}"
+ ports:
+ - '8080:80'
+ - '8443:443'
+ restart: always
+ tty: true
+ volumes:
+ - ./:/app
+ - composer_cache:/var/www/.composer/cache
+ working_dir: /app
+
+volumes:
+ composer_cache:
diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh
new file mode 100644
index 0000000..7ce7385
--- /dev/null
+++ b/docker/entrypoint.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -euo pipefail
+
+echo "=== Container Starting ==="
+echo "Running initialization script..."
+
+# Ensure init script is executable
+chmod +x /usr/local/bin/init.sh
+
+# Execute init script; replace the PID 1 shell
+exec /usr/local/bin/init.sh
+
+# If we get here, everything went well
+echo "=== Container ready ==="
diff --git a/docker/init.sh b/docker/init.sh
new file mode 100644
index 0000000..88ce0c4
--- /dev/null
+++ b/docker/init.sh
@@ -0,0 +1,101 @@
+#!/bin/bash
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m'
+
+echo -e "${GREEN}Starting container setup...${NC}"
+
+# Create PHP-FPM socket directory with proper permissions
+echo -e "${YELLOW}Creating PHP-FPM socket directory...${NC}"
+mkdir -p /var/run/php
+chown www-data:www-data /var/run/php
+chmod 755 /var/run/php
+
+# Create necessary Yii2 directories if they don't exist
+echo -e "${YELLOW}Creating Yii2 directories...${NC}"
+mkdir -p /app/runtime/cache
+mkdir -p /app/runtime/logs
+mkdir -p /app/web/assets
+
+# Configure permissions for Yii2 directories
+echo -e "${YELLOW}Setting up permissions...${NC}"
+
+# Try to set permissions and ownership - handle both mounted volumes and container-only scenarios
+if chown -R www-data:www-data /app/runtime 2>/dev/null; then
+ chmod -R 775 /app/runtime
+ echo -e "${GREEN}✓ Runtime directory configured correctly${NC}"
+else
+ # If chown fails (mounted volume), try chmod only
+ if chmod -R 777 /app/runtime 2>/dev/null; then
+ echo -e "${YELLOW}⚠ Runtime directory permissions set to 777 (mounted volume)${NC}"
+ else
+ echo -e "${RED}✗ Error: Could not configure runtime directory${NC}"
+ fi
+fi
+
+if chown -R www-data:www-data /app/web/assets 2>/dev/null; then
+ chmod -R 775 /app/web/assets
+ echo -e "${GREEN}✓ Assets directory configured correctly${NC}"
+else
+ # If chown fails (mounted volume), try chmod only
+ if chmod -R 777 /app/web/assets 2>/dev/null; then
+ echo -e "${YELLOW}⚠ Assets directory permissions set to 777 (mounted volume)${NC}"
+ else
+ echo -e "${RED}✗ Error: Could not configure assets directory${NC}"
+ fi
+fi
+
+echo -e "${GREEN}Setup completed.${NC}"
+
+# Check if composer.json exists and vendor directory doesn't exist
+if [ -f "/app/composer.json" ] && [ ! -d "/app/vendor" ]; then
+ echo -e "${YELLOW}Installing Composer dependencies...${NC}"
+
+ # Give www-data write access without exposing the tree to everyone
+ chown -R www-data:www-data /app && \
+ chmod -R u+rwX,g+rwX /app
+
+ # Create and configure npm cache directory for www-data
+ mkdir -p /var/www/.npm
+ chown -R www-data:www-data /var/www/.npm
+
+ # Install dependencies with proper environment variables
+ if [ "$YII_ENV" = "prod" ]; then
+ # Production: exclude dev dependencies and optimize autoloader
+ gosu www-data env \
+ HOME=/var/www \
+ COMPOSER_HOME=/var/www/.composer \
+ COMPOSER_CACHE_DIR=/var/www/.composer/cache \
+ npm_config_cache=/var/www/.npm \
+ composer install --no-dev --optimize-autoloader --no-interaction
+ else
+ # Development: include dev dependencies
+ gosu www-data env \
+ HOME=/var/www \
+ COMPOSER_HOME=/var/www/.composer \
+ COMPOSER_CACHE_DIR=/var/www/.composer/cache \
+ npm_config_cache=/var/www/.npm \
+ composer install --optimize-autoloader --no-interaction
+ fi
+
+ echo -e "${GREEN}✓ Composer dependencies installed successfully${NC}"
+fi
+
+# Copy supervisor configuration
+echo -e "${YELLOW}Configuring supervisor...${NC}"
+
+if [ -f "/app/docker/supervisor/supervisord.conf" ]; then
+ cp /app/docker/supervisor/supervisord.conf /etc/supervisor/supervisord.conf
+ echo -e "${GREEN}✓ Supervisor configuration copied successfully${NC}"
+else
+ echo -e "${RED}✗ Error: Supervisor configuration file not found${NC}"
+ exit 1
+fi
+
+echo -e "${GREEN}Starting supervisor daemon...${NC}"
+
+# Start supervisor daemon
+exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile
new file mode 100644
index 0000000..b266f32
--- /dev/null
+++ b/docker/nginx/Dockerfile
@@ -0,0 +1,60 @@
+FROM yiisoftware/yii2-php:8.4-fpm-nginx
+
+# Build arguments for user/group
+ARG USER_ID=1000
+ARG GROUP_ID=1000
+ARG USER_NAME=www-data
+ARG GROUP_NAME=www-data
+
+# Change nginx config
+COPY docker/nginx/nginx.conf /etc/nginx/nginx.conf
+COPY docker/nginx/default.conf /etc/nginx/conf.d/default.conf
+
+# Change PHP config
+COPY docker/php/php.ini /usr/local/etc/php/conf.d/base.ini
+
+# Set document root to /app/web (Yii2 structure)
+WORKDIR /app
+
+# Set composer environment
+ENV COMPOSER_ALLOW_SUPERUSER=1
+
+# Install supervisor, gosu, and Node.js (version simple)
+RUN apt-get update && apt-get install -y --no-install-recommends \
+ supervisor \
+ curl \
+ gosu \
+ && curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \
+ && apt-get install -y nodejs \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+
+# Apply the user/group IDs to www-data
+RUN usermod -u ${USER_ID} www-data && groupmod -g ${GROUP_ID} www-data
+
+# Create composer and npm cache directories with proper ownership
+RUN mkdir -p /var/www/.composer/cache /var/www/.npm && \
+ chown -R www-data:www-data /var/www/.composer /var/www/.npm
+
+# Copy supervisor program configs
+COPY docker/supervisor/conf.d/nginx.conf /etc/supervisor/conf.d/nginx.conf
+COPY docker/supervisor/conf.d/php-fpm.conf /etc/supervisor/conf.d/php-fpm.conf
+
+# Copy queue worker config uncommented for use with yii2-queue
+#COPY docker/supervisor/conf.d/queue.conf /etc/supervisor/conf.d/queue.conf
+
+# Copy scripts
+COPY docker/init.sh /usr/local/bin/init.sh
+COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
+
+# Make scripts executable and validate
+RUN chmod +x /usr/local/bin/init.sh /usr/local/bin/entrypoint.sh && \
+ # Convert any Windows line endings
+ sed -i 's/\r$//' /usr/local/bin/init.sh /usr/local/bin/entrypoint.sh && \
+ # Test that scripts have valid syntax
+ bash -n /usr/local/bin/init.sh && \
+ bash -n /usr/local/bin/entrypoint.sh && \
+ echo "✓ Scripts validated successfully..."
+
+# Use ENTRYPOINT to guarantee execution
+ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf
new file mode 100644
index 0000000..0b75ab6
--- /dev/null
+++ b/docker/nginx/default.conf
@@ -0,0 +1,94 @@
+# HTTP server - Redirect to HTTPS
+server {
+ listen 80;
+ server_name localhost;
+
+ # Redirect all HTTP to HTTPS
+ return 301 https://localhost:8445$request_uri;
+}
+
+# HTTPS server
+server {
+ charset utf-8;
+ client_max_body_size 128M;
+ listen 443 ssl http2;
+ server_name localhost;
+
+ # SSL Configuration
+ ssl_certificate /app/docker/ssl/localhost.pem;
+ ssl_certificate_key /app/docker/ssl/localhost-key.pem;
+
+ # SSL Security Settings
+ ssl_protocols TLSv1.2 TLSv1.3;
+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
+ ssl_prefer_server_ciphers off;
+ ssl_session_cache shared:SSL:10m;
+ ssl_session_timeout 10m;
+
+ # Document root and index file
+ root /app/web;
+ index index.php;
+
+ # Security headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-XSS-Protection "1; mode=block" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
+
+ # Logging
+ access_log /var/log/nginx/ssl_access.log;
+ error_log /var/log/nginx/ssl_error.log;
+
+ # Yii URL rewriting (CRITICAL for Yii2)
+ location / {
+ try_files $uri $uri/ /index.php$is_args$args;
+ }
+
+ # Deny PHP execution in /assets before the generic handler (Yii2 security)
+ location ~ ^/assets/.*\.php$ {
+ deny all;
+ return 403;
+ }
+
+ # PHP handling via PHP-FPM
+ location ~ \.php$ {
+ include fastcgi_params;
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
+ fastcgi_param HTTPS on;
+ fastcgi_pass 127.0.0.1:9000;
+ try_files $uri =404;
+
+ # PHP execution settings
+ fastcgi_read_timeout 300;
+ fastcgi_buffer_size 128k;
+ fastcgi_buffers 4 256k;
+ fastcgi_busy_buffers_size 256k;
+ }
+
+ # Block access to sensitive files
+ location ~ /\.git {
+ deny all;
+ }
+
+ location ~ /\.ht {
+ deny all;
+ }
+
+ # Block access to hidden files/directories
+ location ~* /\. {
+ deny all;
+ }
+
+ # Static files handling with caching
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+ expires 1y;
+ add_header Cache-Control "web, immutable";
+ try_files $uri =404;
+ }
+
+ # Deny access to PHP files in specific directories
+ location ~ ^/(vendor|runtime)/.+\.php$ {
+ deny all;
+ return 404;
+ }
+}
diff --git a/docker/nginx/nginx.conf b/docker/nginx/nginx.conf
new file mode 100644
index 0000000..8a6b419
--- /dev/null
+++ b/docker/nginx/nginx.conf
@@ -0,0 +1,58 @@
+user www-data;
+worker_processes auto;
+pid /run/nginx.pid;
+include /etc/nginx/modules-enabled/*.conf;
+
+events {
+ worker_connections 768;
+ multi_accept on;
+ use epoll;
+}
+
+http {
+ # Basic Settings
+ sendfile on;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+
+ # Security headers
+ server_tokens off;
+
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+
+ # SSL Settings
+ ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM';
+ ssl_ecdh_curve X25519:P-256;
+ ssl_prefer_server_ciphers on;
+
+ # Logging Settings
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+
+ access_log /var/log/nginx/access.log main;
+ error_log /var/log/nginx/error.log warn;
+
+ # Gzip Settings
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_types
+ text/plain
+ text/css
+ text/xml
+ text/javascript
+ application/json
+ application/javascript
+ application/xml+rss
+ application/atom+xml
+ image/svg+xml;
+
+ # Virtual Host Configs
+ include /etc/nginx/conf.d/*.conf;
+ include /etc/nginx/sites-enabled/*;
+}
diff --git a/docker/php/php.ini b/docker/php/php.ini
new file mode 100644
index 0000000..92fe1f7
--- /dev/null
+++ b/docker/php/php.ini
@@ -0,0 +1,23 @@
+# Global PHP configuration for the Docker container
+date.timezone = UTC
+display_errors = Off
+expose_php = Off
+memory_limit = 512M
+post_max_size = 150M
+session.auto_start = Off
+short_open_tag = Off
+upload_max_filesize = 15M
+
+# https://symfony.com/doc/current/performance.html
+# OPcache optimizations
+opcache.enable = 1
+opcache.enable_cli = 1
+opcache.interned_strings_buffer = 16
+opcache.jit = tracing
+opcache.jit_buffer_size = 64M
+opcache.max_accelerated_files = 20000
+opcache.memory_consumption = 256
+opcache.revalidate_freq = 2
+opcache.validate_timestamps = 1
+realpath_cache_size = 4096K
+realpath_cache_ttl = 120
diff --git a/docker/ssl/localhost-key.pem b/docker/ssl/localhost-key.pem
new file mode 100644
index 0000000..4677e62
--- /dev/null
+++ b/docker/ssl/localhost-key.pem
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDJXRl0fj4a5Myo
+WpAN8jevuPIlvS19Yk2243GIXf9rNt7/th4ujMYa7DyGmFE4UiXz/gj5y9vq6/3d
+JNrVPqfcBHKgDdGt4V+c6bauzxhs+QilYzft/9/y/Mglt6Z9ibsvIGnRn6R8gc6W
+dV2KPRUNDTdb83R0Y7CFRydTkTEYl1/mldAz5MNrlIYrr55PbQTG2fZlMXcfmJOh
+TzGvux3skPRD4igTV8rxd0x5RDvcVdSCOx3vpI2ZJ3Vh28Bp934mTNo4Ihsmkn4A
+nzUJsyRNAcXp//8xz9upvmy4FfqXhhR5/oOit4INMjFxkEA2CrX7CYz/EiRhyxWt
+jGmxKXSVAgMBAAECggEARIxC7BtFvRYCbZVW0MiSGGnXVO2PnM1oM0g+D/QfzTnC
+tD4lDCe0ENo2yIL1szyT2vmxyIeTd+eaZjvzmwBXWFjTRJUvuges6tfM7rllUUN9
+o/+gvI6MiEVxRRW9waKvbB2WqFu2PQRbdXDCxRqCHg1PuSepjy2Ym+ZbBuG4Wuwh
+q9vbbqe0isp0YZr8oCeNTbR2Mi2q2DPUTP+WdA0TXulx+IwlIlYnIk0a2IGcdGpX
+io9Mt3/aspZhx7uQf3yBoVMiOWRx/04t4Yc0oxuwLP4atGd7jhKZ2dfgCo6jPPet
+ojIpJgN7vW3o4xRnrv0UuTq9vm2W0ZtV5Zfx4sp/gQKBgQDMBGV5s5itMXSdqoXg
+4xtELye0oMYEd1ih8+ql+VP08nUeflV7vD6+Ci8/x++Azqpr9SU1KBG/9Cj2jK8k
+uLdeKcEuac8DjU1eELGmDnIk4m0supEP3JyrTQCVQYw9Pwvv+jGNz2zi0xppIzoP
+eObU/ftoV3Ue32c9tjMMvzlpBQKBgQD8q57knuAqTVJiIqo1LsRj+j5XQ3IpCYY7
+bVHHi607JywBE8JyerkycYCs6BU4AyZNe8Wp6YJM6qINHgvD13j7CjzSg/YEQVla
+O196Ka08Latvu6D3BqR9oKy+5vto/QNxD0hGToWySZCVjbsc5QRxCbq77GZ05EpI
+owj0Wz9yUQKBgEpFJ3Pgj6otINjs5QPzaU+vIvM8vBmQIPIES93UIF5BjaVmNFRx
+OR4RsxWzAVuQ4LWgbsUlKyEID4mBuZjSrd5XsP3mgvg2Dn458ZIUHDWVQE1SNdDi
+bR5nT9kGHbmGJCBeon+PjYIde7XenxpW1yGevFFF1VtB1OHAXGE9k/bJAoGBAJDa
+wylGfDVERurD/NioiybWHE9i91vXfgEr1yqTRSkYd/3WGjAPc4Ub1S1LkH6gL6FU
+SCn1GSKHkYf7pbsNGOqzH9OAm9YssNEuILqkkhBiDlrsMofsYvky2FZJjfDOvN5g
+aIsGEVf5HM7ghlk2Yql7bna2PLbe+kdSUJvmhCVBAoGBAMY9+yNm9zpHYDLfgmeG
+mUjUrw73G7j+ucRQI6/owgaqJWKlfULG2CQ18XhcpjJcI7R1gADwNwlJN7AjGDtg
+gskDn8yoAGBvaBgkkkv3Z8rKTCGR8mh4bY6G89agY9NphigsaUJrn+4iX59K2/eK
+DNFgybL+X7Mh7P8tmBt1Adua
+-----END PRIVATE KEY-----
diff --git a/docker/ssl/localhost.pem b/docker/ssl/localhost.pem
new file mode 100644
index 0000000..7338a1f
--- /dev/null
+++ b/docker/ssl/localhost.pem
@@ -0,0 +1,26 @@
+-----BEGIN CERTIFICATE-----
+MIIEYjCCAsqgAwIBAgIRAMJ3dsZ62GwPUcMuKwB/pBQwDQYJKoZIhvcNAQELBQAw
+gYcxHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTEuMCwGA1UECwwlVGVy
+YWJ5dGVzb2Z0d1xkZXZlbG9wZXJAVGVyYWJ5dGVzb2Z0dzE1MDMGA1UEAwwsbWtj
+ZXJ0IFRlcmFieXRlc29mdHdcZGV2ZWxvcGVyQFRlcmFieXRlc29mdHcwHhcNMjUw
+NzEwMjIxNjI2WhcNMjcxMDEwMjExNjI2WjBZMScwJQYDVQQKEx5ta2NlcnQgZGV2
+ZWxvcG1lbnQgY2VydGlmaWNhdGUxLjAsBgNVBAsMJVRlcmFieXRlc29mdHdcZGV2
+ZWxvcGVyQFRlcmFieXRlc29mdHcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQDJXRl0fj4a5MyoWpAN8jevuPIlvS19Yk2243GIXf9rNt7/th4ujMYa7DyG
+mFE4UiXz/gj5y9vq6/3dJNrVPqfcBHKgDdGt4V+c6bauzxhs+QilYzft/9/y/Mgl
+t6Z9ibsvIGnRn6R8gc6WdV2KPRUNDTdb83R0Y7CFRydTkTEYl1/mldAz5MNrlIYr
+r55PbQTG2fZlMXcfmJOhTzGvux3skPRD4igTV8rxd0x5RDvcVdSCOx3vpI2ZJ3Vh
+28Bp934mTNo4Ihsmkn4AnzUJsyRNAcXp//8xz9upvmy4FfqXhhR5/oOit4INMjFx
+kEA2CrX7CYz/EiRhyxWtjGmxKXSVAgMBAAGjdjB0MA4GA1UdDwEB/wQEAwIFoDAT
+BgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBRlhRQpnl7nIy6O/r3UOcaY
+LgXBSzAsBgNVHREEJTAjgglsb2NhbGhvc3SHBH8AAAGHEAAAAAAAAAAAAAAAAAAA
+AAEwDQYJKoZIhvcNAQELBQADggGBAIR0dkwyUST+W8TATCZbYThwiYuTSLYyQvyX
+7ieIYWW31nAfcL/WvMt5d80p67mLPvGoGLZSayId7uf6j0LVY2Y94G1z7HOdRd7s
+D7InIrLI0G7pKSXI8mSCczgpx2FD2yIkHaDCdZIYXpkkAhJ6I4hghSG2KZoJ0vhA
+JPTd9VW8ydYykfE619wjZ68RUlve4wtNkmQCrJAWOZMWCNl8O/iz5cWafTr0p4kD
+6qdE/gKvfyWQdc1XgPpZJkpYNw+CGVcpfE7i/++FfspTTY+XyYZClbQjMD1hNGq/
+ATsl8DR4xH5ztUaAkLBRDXpXGal7VyNoBpBot9scDR71YMsTTKf/1NdIt8gPLF4P
+ULwW7UvaHQAj3klPcanEaTv/bgQxor6b8tSwMLqHcU+SdQBjYnWLuAzKTCvL9m73
+MQRRt/N+Z9McSApps0F82eSR3a1HaU5lyH6Es6dLkVnY/ksmzqwi5FADsORSH95M
+GvP9WbrnCQvIW/n3T3pvmuV/BeRkVg==
+-----END CERTIFICATE-----
diff --git a/docker/supervisor/conf.d/nginx.conf b/docker/supervisor/conf.d/nginx.conf
new file mode 100644
index 0000000..3df5802
--- /dev/null
+++ b/docker/supervisor/conf.d/nginx.conf
@@ -0,0 +1,12 @@
+[program:nginx]
+command=/usr/sbin/nginx -g "daemon off;"
+autostart=true
+autorestart=true
+priority=10
+killasgroup=true
+stopasgroup=true
+stopsignal=QUIT
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
diff --git a/docker/supervisor/conf.d/php-fpm.conf b/docker/supervisor/conf.d/php-fpm.conf
new file mode 100644
index 0000000..39399ab
--- /dev/null
+++ b/docker/supervisor/conf.d/php-fpm.conf
@@ -0,0 +1,13 @@
+
+[program:php-fpm]
+command=/usr/local/sbin/php-fpm --nodaemonize
+autorestart=true
+autostart=true
+killasgroup=true
+priority=5
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stopasgroup=true
+stopsignal=QUIT
diff --git a/docker/supervisor/conf.d/queue.conf b/docker/supervisor/conf.d/queue.conf
new file mode 100644
index 0000000..b8eba53
--- /dev/null
+++ b/docker/supervisor/conf.d/queue.conf
@@ -0,0 +1,11 @@
+[program:yii-queue-worker]
+process_name=%(program_name)s_%(process_num)02d
+command=/usr/local/bin/php /app/yii queue/listen --verbose=1 --color=0
+autorestart=true
+autostart=true
+numprocs=4
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+user=www-data
diff --git a/docker/supervisor/supervisord.conf b/docker/supervisor/supervisord.conf
new file mode 100644
index 0000000..d209121
--- /dev/null
+++ b/docker/supervisor/supervisord.conf
@@ -0,0 +1,14 @@
+[supervisord]
+logfile = /proc/self/fd/1
+logfile_maxbytes = 0
+loglevel = info
+nodaemon = true
+pidfile = /var/run/supervisord.pid
+silent = true
+user = root
+
+[include]
+files = /etc/supervisor/conf.d/*.conf
+
+[supervisorctl]
+serverurl = unix:///var/run/supervisor.sock
diff --git a/tests/Acceptance.suite.yml b/tests/Acceptance.suite.yml
index 03e52e8..2e0af2a 100644
--- a/tests/Acceptance.suite.yml
+++ b/tests/Acceptance.suite.yml
@@ -7,5 +7,5 @@ actor: AcceptanceTester
modules:
enabled:
- PhpBrowser:
- url: localhost:8080
+ url: https://localhost:443/
step_decorators: ~
diff --git a/tests/_envs/dockerized.yml b/tests/_envs/dockerized.yml
deleted file mode 100644
index 546f0cc..0000000
--- a/tests/_envs/dockerized.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-modules:
- config:
- PhpBrowser:
- url: https://localhost:443
diff --git a/tests/_envs/php-builtin.yml b/tests/_envs/php-builtin.yml
deleted file mode 100644
index ce9c804..0000000
--- a/tests/_envs/php-builtin.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-extensions:
- enabled:
- - Codeception\Extension\RunProcess:
- 0: php -d variables_order=EGPCS -S localhost:8085 -t web
- sleep: 1
-modules:
- config:
- PhpBrowser:
- url: http://localhost:8085
From 34f2772252f53845e4d6900f1fb96192727834f7 Mon Sep 17 00:00:00 2001
From: Wilmer Arambula
Date: Wed, 3 Sep 2025 05:07:15 -0400
Subject: [PATCH 2/5] fix(build): Update container references from
`yii2-apache` to `yii2-nginx` in build workflow.
---
.github/workflows/build.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 6240e0f..e9ab2c4 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -38,10 +38,10 @@ jobs:
run: |
echo "Waiting 30 seconds for container initialization..."
sleep 30
- docker logs yii2-apache
+ docker logs yii2-nginx
- name: Codeceptcion build.
- run: docker exec yii2-apache vendor/bin/codecept build
+ run: docker exec yii2-nginx vendor/bin/codecept build
- name: Run codeception tests.
- run: docker exec yii2-apache vendor/bin/codecept run
+ run: docker exec yii2-nginx vendor/bin/codecept run
From 4813ad0a579a730d5592c182ae3edc4762cf2c60 Mon Sep 17 00:00:00 2001
From: Wilmer Arambula
Date: Wed, 3 Sep 2025 05:14:37 -0400
Subject: [PATCH 3/5] fix(docs): Update `README.md` for `Nginx` deployment
details and badge links.
---
README.md | 41 +++++++++--------------------------------
1 file changed, 9 insertions(+), 32 deletions(-)
diff --git a/README.md b/README.md
index c8bc47d..a4aee63 100644
--- a/README.md
+++ b/README.md
@@ -16,10 +16,10 @@
-
+
-
+
@@ -40,23 +40,6 @@ A modern, Bootstrap 5-powered Yii2 application template designed for rapid web-a
- ✅ **Modern Bootstrap 5 UI** - Responsive, mobile-first design with latest Bootstrap components.
- ✅ **Testing Ready** - Codeception test suite with examples for functional and unit testing.
-## Available deployment options
-
-### Traditional Web Servers
-
-Classic request-per-process model; simple, widely supported (for example, Apache).
-
-[](https://github.com/yii2-extensions/app-basic/tree/apache)
-
-### High-Performance Worker Mode
-
-Long-running PHP workers for higher throughput and lower latency.
-
-[](https://github.com/yii2-extensions/app-basic/tree/franken-php)
-[](https://github.com/yii2-extensions/app-basic/tree/road-runner)
-
-> For setup instructions, see `README.md` in each branch.
-
## How it works
The Yii2 Web Application Basic template provides a complete foundation for building modern web applications. Unlike starting from scratch, this template includes.
@@ -78,23 +61,19 @@ The Yii2 Web Application Basic template provides a complete foundation for build
### Installation
```bash
-composer create-project --prefer-dist yii2-extensions/app-basic:^0.1 app-basic
+composer create-project --prefer-dist yii2-extensions/app-basic:dev-nginx app-basic
cd app-basic
```
### Quick start
-Start development server
+Start Nginx
```bash
-# Using built-in PHP server
-php -S localhost:8080 -t web
-
-# Or using Yii console command
-./yii serve
+docker-compose up -d
```
-> Your application will be available at `http://localhost:8080` or at the address set in `--address` option.
+> Your application will be available at `https://localhost:8443`.
#### Directory structure
@@ -153,15 +132,13 @@ final class SiteController extends Controller
## Package information
-[](https://packagist.org/packages/yii2-extensions/app-basic)
-[](https://packagist.org/packages/yii2-extensions/app-basic)
-
+[](https://github.com/yii2-extensions/app-basic/tree/nginx)
## Quality code
-[](https://codecov.io/github/yii2-extensions/app-basic)
+[](https://codecov.io/github/yii2-extensions/app-basic)
[](https://github.com/yii2-extensions/app-basic/actions/workflows/static.yml)
-[](https://github.styleci.io/repos/165419144?branch=main)
+[](https://github.styleci.io/repos/165419144?branch=nginx)
## Documentation
From c5214d5ec55e8e690dcd9677d239f9bb80200a75 Mon Sep 17 00:00:00 2001
From: Wilmer Arambula
Date: Wed, 3 Sep 2025 05:51:50 -0400
Subject: [PATCH 4/5] Apply fixed review coderabbitai nitpick comments.
---
.github/workflows/build.yml | 20 +++++++++++---------
docker/nginx/default.conf | 4 ++--
docker/php/php.ini | 2 ++
docker/supervisor/conf.d/queue.conf | 9 +++++++--
4 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index e9ab2c4..55f94a8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -25,20 +25,22 @@ jobs:
- name: Checkout.
uses: actions/checkout@v5
- - name: Install docker compose.
+ - name: Show docker version.
run: |
- sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
- sudo chmod +x /usr/local/bin/docker-compose
- docker-compose --version
+ docker version
+ docker compose version
- name: Build and start containers.
- run: docker-compose up -d --build
+ run: docker compose up -d --build
- - name: Wait for container to be ready.
+ - name: Wait for readiness.
run: |
- echo "Waiting 30 seconds for container initialization..."
- sleep 30
- docker logs yii2-nginx
+ for i in {1..60}; do
+ if docker exec yii2-nginx sh -lc "curl -ksS -o /dev/null -w '%{http_code}' https://localhost | grep -qE '200|302'"; then
+ echo "Service is ready"; exit 0; fi
+ sleep 2
+ done
+ echo "Service not ready"; docker logs yii2-nginx; exit 1
- name: Codeceptcion build.
run: docker exec yii2-nginx vendor/bin/codecept build
diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf
index 0b75ab6..c09bc07 100644
--- a/docker/nginx/default.conf
+++ b/docker/nginx/default.conf
@@ -4,7 +4,7 @@ server {
server_name localhost;
# Redirect all HTTP to HTTPS
- return 301 https://localhost:8445$request_uri;
+ return 301 https://$host$request_uri;
}
# HTTPS server
@@ -82,7 +82,7 @@ server {
# Static files handling with caching
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
- add_header Cache-Control "web, immutable";
+ add_header Cache-Control "public, immutable";
try_files $uri =404;
}
diff --git a/docker/php/php.ini b/docker/php/php.ini
index 92fe1f7..aa22113 100644
--- a/docker/php/php.ini
+++ b/docker/php/php.ini
@@ -2,6 +2,8 @@
date.timezone = UTC
display_errors = Off
expose_php = Off
+log_errors = On
+error_log = /proc/self/fd/2
memory_limit = 512M
post_max_size = 150M
session.auto_start = Off
diff --git a/docker/supervisor/conf.d/queue.conf b/docker/supervisor/conf.d/queue.conf
index b8eba53..f6f2f60 100644
--- a/docker/supervisor/conf.d/queue.conf
+++ b/docker/supervisor/conf.d/queue.conf
@@ -2,8 +2,13 @@
process_name=%(program_name)s_%(process_num)02d
command=/usr/local/bin/php /app/yii queue/listen --verbose=1 --color=0
autorestart=true
-autostart=true
-numprocs=4
+# Enable only after installing yiisoft/yii2-queue; flipped on via image build or entrypoint.
+autostart=false
+# Keep demo light; can be raised later.
+numprocs=1
+stopasgroup=true
+killasgroup=true
+stopsignal=TERM
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stdout_logfile=/dev/stdout
From 478e4c8ffc90ac54ed042f69e338059a448e20f6 Mon Sep 17 00:00:00 2001
From: Wilmer Arambula <42547589+terabytesoftw@users.noreply.github.com>
Date: Wed, 3 Sep 2025 06:01:48 -0400
Subject: [PATCH 5/5] fix(docs): Improve clarity in deployment options
description and add `Nginx` badge in `README.md`. (#182)
---
CHANGELOG.md | 1 +
README.md | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8dec76f..0179e20 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@
- Bug #172: Update badge label from `PHPUnit` to `Codeception` in `README.md` (@terabytesoftw)
- Bug #175: Update allowed IPs in configuration for development purposes in `configuration.md` (@terabytesoftw)
- Bug #177: Add missing config path to ECS configuration in `ecs.php` (@terabytesoftw)
+- Bug #182: Improve clarity in deployment options description and add `Nginx` badge in `README.md` (@terabytesoftw)
## 0.1.0 August 31, 2025
diff --git a/README.md b/README.md
index c8bc47d..d7ff01f 100644
--- a/README.md
+++ b/README.md
@@ -44,9 +44,10 @@ A modern, Bootstrap 5-powered Yii2 application template designed for rapid web-a
### Traditional Web Servers
-Classic request-per-process model; simple, widely supported (for example, Apache).
+Classic web-server + PHP-FPM setup; simple and widely supported for deployment.
[](https://github.com/yii2-extensions/app-basic/tree/apache)
+[](https://github.com/yii2-extensions/app-basic/tree/nginx)
### High-Performance Worker Mode
@@ -156,7 +157,6 @@ final class SiteController extends Controller
[](https://packagist.org/packages/yii2-extensions/app-basic)
[](https://packagist.org/packages/yii2-extensions/app-basic)
-
## Quality code
[](https://codecov.io/github/yii2-extensions/app-basic)