codechap / yii3-oci-deploy
OCI deployment commands for Yii3 applications
Requires
- php: ^8.3
- symfony/console: ^7.0
This package is auto-updated.
Last update: 2026-03-30 06:28:57 UTC
README
Reusable Oracle Cloud Infrastructure (OCI) deployment commands for Yii3 applications. Provides a complete server lifecycle — provision, setup, deploy, update, SSL — driven entirely from php yii console commands.
Built for ARM-based (aarch64) Ubuntu 24.04 instances running RoadRunner behind an Nginx reverse proxy.
Installation
Add as a path repository in your project's composer.json:
{
"repositories": [
{
"type": "path",
"url": "/home/codechap/dev/packages/yii3-oci-deploy"
}
],
"require": {
"codechap/yii3-oci-deploy": "@dev"
}
}
Then run composer update codechap/yii3-oci-deploy.
Setup
1. Implement the config interface
Create a class that implements Codechap\OciDeploy\OciConfigInterface with your project-specific values:
namespace App\Console; use Codechap\OciDeploy\OciConfigInterface; final class OciConfig implements OciConfigInterface { public function displayName(): string { return 'MyApp'; } public function domain(): string { return 'myapp.com'; } public function appUser(): string { return 'myapp'; } public function remotePath(): string { return '/home/myapp/htdocs/myapp.com'; } public function canonicalWww(): bool { return false; } // bare domain canonical public function systemdRequires(): ?string { return null; } // or 'mariadb.service' public function prodIp(): ?string { return '1.2.3.4'; } // default IP for deploy commands // ... all other interface methods }
2. Register the DI binding
Create config/common/di/oci.php:
use App\Console\OciConfig; use Codechap\OciDeploy\OciConfigInterface; return [ OciConfigInterface::class => OciConfig::class, ];
3. Register commands
In config/console/commands.php:
use App\Console; use Codechap\OciDeploy; return [ 'oci:images' => OciDeploy\OciImagesCommand::class, 'oci:provision' => OciDeploy\OciProvisionCommand::class, 'oci:setup' => Console\OciSetupCommand::class, 'oci:ssl' => OciDeploy\OciSslCommand::class, 'oci:deploy' => Console\OciDeployCommand::class, 'oci:update' => OciDeploy\OciUpdateCommand::class, ];
4. Extend the abstract commands
oci:setup and oci:deploy are abstract to allow project-specific steps (DB migrations, Tailwind builds, etc.):
namespace App\Console; use Codechap\OciDeploy\AbstractOciSetupCommand; use Symfony\Component\Console\Attribute\AsCommand; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Output\OutputInterface; #[AsCommand(name: 'oci:setup', description: 'Setup a new MyApp instance')] final class OciSetupCommand extends AbstractOciSetupCommand { protected function afterCoreSetup(OutputInterface $output, string $ip): int { // Run DB migrations, build assets, etc. return Command::SUCCESS; } }
Same pattern for OciDeployCommand extending AbstractOciDeployCommand with an afterCoreDeploy() hook.
5. Create project-specific files
Each project needs:
scripts/cloud-init.sh— OS-level provisioning (PHP, Nginx, DB, users, directories)scripts/rr.prod.yaml— Production RoadRunner config (localhost-bound, production logging)
Commands
oci:images
Lists available Ubuntu ARM64 images in your OCI compartment.
php yii oci:images
oci:provision
Launches a new OCI compute instance with cloud-init provisioning.
php yii oci:provision --image-id=<OCID> [--name=<display-name>]
What it does:
- Validates OCI CLI installation and SSH key
- Launches a
VM.Standard.A1.Flexinstance with the configured OCPUs, memory, and boot volume - Injects your SSH public key and cloud-init script as user-data
- Waits for the instance to reach RUNNING state
- Retrieves and displays the public IP
oci:setup
Full automated setup of a freshly provisioned instance.
php yii oci:setup [<IP_ADDRESS>]
The IP argument is optional for all commands. When omitted, the value from prodIp() in your config is used.
What it does:
- Verifies SSH access to the instance
- Waits for cloud-init to complete (polls log file, up to 10 minutes)
- Copies SSH keys to the app user account
- Rsyncs project code (excludes runtime, vendor, tests, etc.)
- Downloads the RoadRunner binary (ARM64)
- Fixes file ownership and permissions
- Runs
composer install --no-dev --optimize-autoloader - Deploys the environment config to
/etc/<app>/env - Deploys the production RoadRunner config
- Creates and starts a systemd service for RoadRunner
- Clears the route cache
- Runs any project-specific steps via
afterCoreSetup() - Verifies the site responds
oci:ssl
Obtains a Let's Encrypt certificate and configures Nginx for HTTPS.
php yii oci:ssl [<IP_ADDRESS>]
What it does:
- Verifies DNS resolves to the server IP
- Issues a certificate via acme.sh for the domain and www subdomain
- Installs the certificate to
/etc/nginx/ssl-certificates/ - Deploys an HTTPS Nginx config with:
- TLS 1.2/1.3, strong ciphers
- HSTS header (1 year)
- Correct canonical redirect (www vs bare domain, based on
canonicalWww()) - Reverse proxy to RoadRunner on 127.0.0.1:8080
- Tests and reloads Nginx
Auto-renewal is handled by the acme.sh cron job installed during cloud-init.
oci:deploy
Full deployment with composer install.
php yii oci:deploy [<IP_ADDRESS>] [--skip-composer]
What it does:
- Rsyncs code
- Deploys production RoadRunner config
- Runs
composer install(unless--skip-composer) - Runs any project-specific steps via
afterCoreDeploy() - Clears route cache
- Restarts the RoadRunner systemd service
- Verifies the site responds
oci:update
Fast incremental code push. No composer install, no rebuilds.
php yii oci:update [<IP_ADDRESS>]
This is the recommended command for day-to-day code changes. It rsyncs code, deploys the RR config, clears cache, and restarts the service. When prodIp() is configured, the IP can be omitted:
php yii oci:update
Architecture
OciConfigInterface <-- Your project implements this
|
+-- OciImagesCommand (concrete, final)
+-- OciProvisionCommand (concrete, final)
+-- OciSslCommand (concrete, final)
+-- OciUpdateCommand (concrete, final)
+-- AbstractOciSetupCommand (abstract, afterCoreSetup hook)
+-- AbstractOciDeployCommand (abstract, afterCoreDeploy hook)
OciSshTrait <-- SSH/SCP helpers used by all commands
All commands receive OciConfigInterface via constructor injection (Yii3 DI). The config interface provides every project-specific value — OCI region, instance shape, domain, paths, users, env content, etc.
Prerequisites
- PHP 8.3+
- OCI CLI installed and configured (
~/.oci/config) - SSH key pair (
~/.ssh/id_rsa.pub) - rsync installed locally