Before you begin
You need:- A Drupal site deployed on Upsun.
- The Upsun CLI installed and authenticated.
1. Install Drush
Add Drush to your project as a Composer dependency:.upsun/config.yaml
2. Make Drush available on your path
Composer installs Drush to your project’svendor/bin directory, which isn’t on your path by default.
This is what makes running drush directly return drush: command not found.
Add the following to a .environment file at the root of your app so Drush (and any other Composer binary) is available whenever you connect:
.environment
3. Set the site URI
Many Drush commands (such asdrush uli for one-time login links) need to know your site’s URL.
Set DRUSH_OPTIONS_URI from your routes in the same .environment file:
.environment
Run Drush commands
There are three ways to run Drush commands against a deployed environment, depending on your use case.Using the CLI
The Upsun CLI has a built-indrush alias that runs a command against a remote environment without opening a full SSH session:
The
upsun CLI doesn’t support generating Drush aliases, so you’ll need to set them up manually.
This is unlike the platform CLI, which includes a local:drush-aliases command for this.Over SSH
To run Drush as part of a longer interactive session, connect over SSH and run Drush directly, or pass the command inline:feature with the name of the environment you want to target.
Set up Drush aliases manually
A Drush alias lets you rundrush @myproject.main <COMMAND> from your local machine without connecting over SSH first.
Since the Upsun CLI doesn’t generate these for you, create them by hand:
-
Get the SSH host and username for each environment you want an alias for:
-
Get the environment’s primary URL with the
urlcommand: -
Create a site alias file at
drush/sites/<PROJECT_NAME>.site.ymlin your local repository, with one entry per environment:drush/sites/myproject.site.ymlrootis your app’s docroot on the remote environment, the same directory Drush runs from in deploy hooks. -
Run commands against an alias instead of connecting manually:
In hooks
To run Drush automatically on every deployment, add it to adeploy or post_deploy hook.
This assumes Drush is already on your path. Without that, the hook fails with drush: command not found:
.upsun/config.yaml
drush status --field=bootstrap check confirms Drupal is installed and bootstraps successfully before running further commands,
which avoids failed deployments on a fresh environment that hasn’t been installed yet.
Common commands
The following Drush commands are frequently useful in an Upsun workflow:Troubleshooting
composer require drush/drush fails
If Composer reports that it can’t find drush/drush, or blocks the install over a security advisory, this is usually a version mismatch rather than a network issue:
- Package not found: Drush’s minimum PHP requirement increases with each major version. If your app’s PHP version is older than any available Drush release supports, Composer reports it as unable to find a matching package. Check your app’s PHP version against Drush’s current requirements, and pin to an older Drush major version if you can’t upgrade PHP yet, for example
composer require drush/drush:^11. - Security-advisory conflict: If your
composer.jsonincludes a package likeroave/security-advisories, it blocks installing versions with known vulnerabilities. Composer’s error output names the exact conflicting package and version — upgrade Drush past that range to resolve it.
drush: command not found
Confirm Drush is installed as a Composer dependency and that
your path includes vendor/bin.
A command returns the wrong domain
If a command that depends on the site URI (such asdrush uli) returns the wrong domain or an error,
confirm DRUSH_OPTIONS_URI is set for the environment you’re running against.
Drush can’t query the database on a multisite install
On a multisite Drupal install, running a baredrush command can fail with an error like the following:
web/sites).
Specify the site with the -l (--uri) flag. Despite the flag’s name, use the site’s subdirectory name (for example, site1), not a full URL: