PHPackages                             codechap/yii3-oci-deploy - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. codechap/yii3-oci-deploy

ActiveLibrary

codechap/yii3-oci-deploy
========================

OCI deployment commands for Yii3 applications

01↑2900%PHP

Since Mar 29Pushed 1mo agoCompare

[ Source](https://github.com/codeChap/yii3-oci-deploy)[ Packagist](https://packagist.org/packages/codechap/yii3-oci-deploy)[ RSS](/packages/codechap-yii3-oci-deploy/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

yii3-oci-deploy
===============

[](#yii3-oci-deploy)

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
------------

[](#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
-----

[](#setup)

### 1. Implement the config interface

[](#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

[](#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

[](#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

[](#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

[](#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
--------

[](#commands)

### `oci:images`

[](#ociimages)

Lists available Ubuntu ARM64 images in your OCI compartment.

```
php yii oci:images

```

### `oci:provision`

[](#ociprovision)

Launches a new OCI compute instance with cloud-init provisioning.

```
php yii oci:provision --image-id= [--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`

[](#ocisetup)

Full automated setup of a freshly provisioned instance.

```
php yii oci:setup []

```

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//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`

[](#ocissl)

Obtains a Let's Encrypt certificate and configures Nginx for HTTPS.

```
php yii oci:ssl []

```

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`

[](#ocideploy)

Full deployment with composer install.

```
php yii oci:deploy [] [--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`

[](#ociupdate)

Fast incremental code push. No composer install, no rebuilds.

```
php yii oci:update []

```

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
------------

[](#architecture)

```
OciConfigInterface
