codechap/yii3-oci-deploy

OCI deployment commands for Yii3 applications

Maintainers

Package info

github.com/codeChap/yii3-oci-deploy

pkg:composer/codechap/yii3-oci-deploy

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

dev-main 2026-03-30 06:28 UTC

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.Flex instance 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:

  1. Verifies SSH access to the instance
  2. Waits for cloud-init to complete (polls log file, up to 10 minutes)
  3. Copies SSH keys to the app user account
  4. Rsyncs project code (excludes runtime, vendor, tests, etc.)
  5. Downloads the RoadRunner binary (ARM64)
  6. Fixes file ownership and permissions
  7. Runs composer install --no-dev --optimize-autoloader
  8. Deploys the environment config to /etc/<app>/env
  9. Deploys the production RoadRunner config
  10. Creates and starts a systemd service for RoadRunner
  11. Clears the route cache
  12. Runs any project-specific steps via afterCoreSetup()
  13. 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:

  1. Verifies DNS resolves to the server IP
  2. Issues a certificate via acme.sh for the domain and www subdomain
  3. Installs the certificate to /etc/nginx/ssl-certificates/
  4. 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
  5. 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:

  1. Rsyncs code
  2. Deploys production RoadRunner config
  3. Runs composer install (unless --skip-composer)
  4. Runs any project-specific steps via afterCoreDeploy()
  5. Clears route cache
  6. Restarts the RoadRunner systemd service
  7. 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