Skip to main content

Deployment Script

The deployment system is the main feature in DOM Cloud. It let's you to perform automatic configuration all by convenience of a single script. It's also can be used as a CI (Continous Integration) tool that perform some tasks inside your website.

This page is meant for average technical user which already understand how SSH and linux commands works in a basic way. If not, please start from Getting Started and General NGINX Guide as we have a plenty of existing deployment templates. If you need to customize it, learn how SSH works first from other resources or ask someone to help you.

The deployment system is accessible through Setup -> Deploy tab in the navigation once inside a website.

The buttons explained:

  • Add a deployment task: Add a new deployment task as we will describe through this page.
  • Debug Manually: This opens the editor menu to let you open SSH/Filestash and do tasks manually.
  • Start Over: Open a dialog to let you create a new template or upload new apps here like in the create tab.

For common script deployments, there's existing recipes from the deployment page or recipe repository.

We try to make it as simple as possible to understand. We also make our backend processing open sourced so you take a better view of how it works if you want that.

The script runner is in YAML format. Here's a simple overview:

source: # Source URL to replace all files in "public_html"
features: # List of features to be enabled or configured
nginx: # NGINX configuration to be set for current website
commands: # List of SSH commands that will be executed inside "public_html"

Each of these keys are explained in details below.

source

Source URL from internet to replace all files in ~/public_html. Common examples:

# Clones octocat.github.io to  "~/public_html"
source: https://github.com/octocat/octocat.github.io
# Download latest WordPress and extracts it from "wordpress" folder
source:
url: https://wordpress.org/latest.zip
directory: wordpress
# Removes all files and directories in "~/public_html"
source: clear

Type: string or object. If it a string, it will be the source.url.

If this value is set, it will download contents inside the directory. The content can be either a ZIP file or a Git repository (to perform clone), or clear to simply clears the content.

tip

This option is useful if your files is already in a public repository such as GitHub. If you need to upload the files from your local device use Webmin File Manager.

danger

This option will always overwrite all contents inside the website. Use with caution!

source.url

A required string contains a compressed file or GIT URL to download or clone, or clear to just clear all files without it.

Supports http://, https://, ftp:// or ssh://.

source.type

Either of extract (default) or clone. If omitted, it autodetects to clone if either:

  • The host is github.com, gitlab.com or bitbucket.com and not ending with .tar.gz or .zip.
  • The URL scheme is ssh://

When source.type is extract

This will peform extraction from a compressed file. The URL must ending with .tar.gz, .tar.xz, .tar.bz2 to be extracted with tar command or otherwise it be assumed to be a .zip file. A chmod -R 0750 is performed after extraction to normalize file permissions to avoid inconsistency.

Additional options for this source.type include

source.directory

Specify the folder name to move out of ZIP file after extraction. This also can be specified from url's hash. If omitted, no move operation performed.

When source.type is clone

This will perform git clone. Additional options for this source.type include

source.branch

Specify the clone branch to get checked out. This also can be specified from directory or url's hash. If omitted, the default (master/main) branch will be checked out.

source.depth

Either blobless (default), treeless or shallow. In order, they will add --filter=blob:none, --filter=tree:0 or --depth 1. Blobless is the default to ensure fast cloning and minimal .git size.

source.submodules

Either false (default) or true. If true, it will add --recurse-submodules which will clone all submodules too.

source.credentials.github.ssh and source.credentials.github.sshPub

Facilitates cloning of private repo using ssh:// protocol scheme. It's a string of file contents of private and public key.

Only private key ssh is mandatory, the public key sshPub is only for reference. The ssh will be written to $HOME/.ssh/id_github_com while the public key will be written to $HOME/.ssh/id_github_com.pub. It will also write this to SSH config file $HOME/.ssh/config:

Host github.com
StrictHostKeyChecking no
IdentityFile ~/.ssh/id_github_com

features

Enable, configure or disable one or more features in the website. Common examples:

# Enable MariaDB and PostgreSQL and Valkey
features:
- mysql
- postgresql
- valkey
# Install latest Node.js and Python in the server
features:
- node
- python
# Ask for a new TLS certificate from let's encrypt
features:
- ssl

Type: Array of string or object. If one item is a string, it will be converted to object (.e.g. mysql on become { mysql: on }).

This configures all features available for the host in DOM Cloud.

mysql

Configure MariaDB (MySQL-like) Database Server.

  • mysql or mysql on Enable MariaDB and create default DB.
  • mysql create <dbname> Create a new database with <username>_<dbname>.
  • mysql drop <dbname> Drop a database with <username>_<dbname>.
  • mysql modify-pass <newpass> Set account password of <username> with <newpass>.
  • mysql off. Disables mysql feature. Caution: Also drop all DB permanently.

When mysql is enabled, MYPASSWD will be available in the envar as the MariaDB password.

postgresql

Configure PostgreSQL Database Server.

  • postgresql or postgresql on Enable PostgreSQL and create default DB.
  • postgresql create <dbname> Create a new database with <username>_<dbname>.
  • postgresql drop <dbname> Drop a database with <username>_<dbname>.
  • postgresql modify-pass <newpass> Set account password of <username> with <newpass>.
  • postgresql off. Disables postgresql feature. Caution: Also drop all DB permanently.

When postgresql is enabled, PGPASSWD will be available in the envar as the PostgreSQL password.

redis

Configure Valkey (Redis-like) Database Server.

  • redis or redis on Enable Valkey and create default DB.
  • redis create <dbname> Create a new database with <username>_<dbname>.
  • redis drop <dbname> Drop a database with <username>_<dbname>.
  • redis off. Disables redis feature. Caution: Also drop all DB permanently.

When redis feature is set, RDPASSWD will be available in the envar as the Valkey ACL password. Note that this "database" is refering to ACL-Prefixed keys, not the number-indexed databased.

dns

Configure BIND DNS Server.

  • dns or dns on Enable DNS server.
  • dns add <type> <value> Add a record.
  • dns rem <type> <value> Deletes a record.
  • dns off. Disables dns feature. Caution: Also drop all DNS records.

You can add multiple records with lists. For example:

features:
- dns:
- add a sub-a 1.2.3.4
- add aaaa sub-a 2001:1:2:3:4:5:6:7
- add cname sub-b example.net.
- add cname sub-c example.net.

DNS records for child server is handled automatically.

info

When adding CNAME values, looks out for the trailing dot (.) at the end of CNAME values.

It is required to specify the root domain, otherwise it will be appended with the parent domain.

tip

DNS records is also configurable via Webmin DNS.

firewall

Configure outgoing firewall in your domain. Only configurable for users with Lite plan or above.

  • firewall on or firewall Enable firewall (default for free users).
  • firewall off Disable firewall (default for subscribing users).

Firewall is an additional protection to make sure the host won't send any outgoing request not defined in the whitelist.

See the relevant security description regarding this feature.

ssl

Configure SSL or Attempt to renew SSL certificate with Let's Encrypt.

  • ssl, renew SSL certificate with shared domain (if available) or using Let's Encrypt if it not exists yet or starts to expire.
  • ssl letsencrypt, renew SSL certificate with Let's Encrypt forcibly.
  • ssl selfsign, renew SSL certificate with Self-signed certificate forcibly.

To configure SSL redirect option:

  • ssl always Always redirect HTTP to HTTPS
  • ssl on (default) Enable both HTTP to HTTPS
  • ssl off Disable HTTPS access (not recommended)

http

Configure preferred HTTP version for HTTPS.

  • http 1 (default) use HTTP version 1 only
  • http 3 use HTTP version 3 if browser supports it

Using HTTP version 3 can be much faster.

www

Configure how to handle www subdomain prefix. When www subdomain prefix is handled and that www subdomain is configured with correct IP to the server, it will show the website as the non-www (apex) domain.

  • off Do not handle www subdomain prefix
  • on (default) Handle both www subdomain and the apex domain
  • enforce (not recommended) Always only handle www subdomain prefix

root

Set directory root path. This also changes the root directive in NGINX config.

info

root is configurable both in features: and nginx:. The following is equivalent:

features:
- root: public_html/public
nginx:
root: public_html/public

docker

Configure Docker capability. Only for users with Kit and Pro plan.

  • docker on or docker Enable docker.
  • docker off Disable docker.

With this enabled it doing three things:

  • usermod --add-subuids --add-subgids $USERNAME to allow docker rootless using sub uids for assigning containers.
  • loginctl enable-linger $USERNAME to allow processes not get killed when SSH session terminates.
  • dockerd-rootless-setuptool.sh install to install docker daemon in user-scope.

The docker CLI is always available regardless of this settings as this is provided from a system-wide install packages. Read more on how to deploy with docker.

neovim

Installs Neovim NvChad. This simply run git clone https://github.com/NvChad/starter ~/.config/nvim. After this installed, run nvim in terminal and type :MasonInstallAll to install missing neovim packages. Read more about Neovim with NvChad.

dnf

Installs additional packages similar to OS-wide dnf install to ~/usr, for example:

  • dnf ImageMagick
  • dnf ffmpeg

ssh

Whether to enable or disable SSH login. This also has an impact related to Filestash, Webmin and VS Code remote tooling. Turning off ssh can be necessary to increase security.

  • ssh on enable login
  • ssh off disable login

It's still possible to run the terminal with ssh off via webmin terminal or deployment commands.

fix

Fix file permission by running chmod 0750 to all directories in the website except ~/homes.

lock

Lock files modification by changing the specified folder owner to nobody.

Specify the folder to lock using lock <dirpath>. If <dirpath> is not set, it will lock ~/public_html.

Note that there's no chmod beforehand, so if you lock directories with 0700 file mode, you and NGINX will also can't read the file.

Locking files modification is beneficial if you think someone messed up code or to prevent tampering with website content if your site has been hacked.

unlock

Unlock files modification by changing the specified folder owner back to the home user. This is the reverse of lock feature.

Specify the folder to unlock using unlock <dirpath>. If <dirpath> is not set, it will unlock ~/public_html.

You can combine both lock and unlock to finetune what to lock and unlock.

features:
- lock public_html
- unlock public_html/.cache

php

Set PHP (FastCGI) version. Available options:

  • php 7.4
  • php 8.1
  • php 8.2
  • php 8.3
  • php latest (default)

Remember that php 8.x is an active release. Changing this version also sets the php (and composer) to the right version in CLI/SSH.

PHP files that served through NginX are served with php-fpm (FastCGI Process Manager).

You can't install custom PHP versions or any PHP modules since these are installed by RHEL system packages. However if you're expert enough you can install a PHP binary yourself then use Passenger Phusion GLS to run PHP by FastCGI. Read more on how to deploy PHP websites.

node

Install specific NodeJS version. Available options:

  • node or node latest
  • node lts
  • node beta
  • node x.y.z
  • node off

By default it's Node 20.x provided from RHEL system packages. Note that the default system doesn't provide Corepack and supplemental package managers like yarn (berry version) or pnpm.

This also sets the node (and npm, yarn, etc.) to the right version in CLI/SSH and corepack will enabled. This installation is powered by nvm. All given node version is downloaded in binary/compiled version from the official registry to keep switching version fast. Read more on how to deploy Node apps.

python

Install specific Python version. Available options:

  • python or python latest
  • python lts or python stable
  • python system
  • python x.y
  • python x.y.z
  • python off

By default it's Python 3.9 provided from RHEL system packages, equivalent with python system.

This also sets the python (and pip) to the right version in CLI/SSH. This installation is powered by pyenv. If binary version is available then it will use it to make switching fast.

If you have problem creating virtual envs please using pyenv virtualenv or just use version python system which also works and always isolated for current user.

The difference with python system and python off is the latter will remove pyenv and all former local python installations.

The installer will try to download binary/compiled version from community builds if available to keep switching version fast. Read more on how to deploy Python apps.

ruby

Install specific Ruby version. Available options:

  • ruby or ruby latest
  • ruby lts or ruby stable
  • ruby x.y.z
  • ruby trufferuby
  • ruby off

By default it's Ruby 3.0 provided from RHEL system packages. All instalations with ruby gems has --no-document implied from global settings to keep installation minimal and fast.

This installation is powered by rvm. It will try to download compiled version from custom RVM builds if available to keep switching version fast. Read more on how to deploy Ruby apps.

deno

Install specific Deno version. Available options:

  • deno or deno latest
  • deno beta
  • deno x.y.z
  • deno off

There's no Deno installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by webi. Read more on how to deploy Deno apps.

bun

Install specific Bun.js version. Available options:

  • bun or bun latest
  • bun x.y.z
  • bun off

There's no Bun.js installed in system-wide binaries. You must specify this feature to make it available.

When configuring NGINX with bun you have to prefix it with proxfix which is installed by default.

This installation is powered by webi. Read more on how to deploy Bun.js apps.

go

Install specific Go version. Available options:

  • go or go latest
  • go x.y.z
  • go off

There's no Go installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by webi. Read more on how to deploy Go apps.

rust

Install specific Rust version. Available options:

  • rust or rust latest
  • rust x.y.z
  • rust off

There's no Rust installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by rustup. It will install minimal profile to keep switching versions fast. Read more on how to deploy Rust apps.

java

Install specific Java version. Available options:

  • java or java latest
  • java stable or java lts
  • java x.y.z
  • java off

There's no Java installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by Adoptium Project. Only latest build from them in each major version (as low as jdk 8) is available to download using this feature. Read more on how to deploy Java apps.

dotnet

Install specific .NET Core version. Available options:

  • dotnet or dotnet latest
  • dotnet x.y.z
  • dotnet off

There's no .NET Core installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by Microsoft .NET Core builds. Only versions provided by them is available to install. Read more on how to deploy .NET Core apps.

zig

Install specific Zig version. Available options:

  • zig or zig latest
  • zig beta
  • zig x.y.z
  • zig off

There's no Zig installed in system-wide binaries. You must specify this feature to make it available.

This installation is powered by webi. Read more on how to deploy Zig apps.


nginx

Configures NGINX for a given website. Can be a string or object. If passed as string, it will be converted into YAML object before config gets applied. You are only allowed to change NGINX properties based on what YAML object can permits.

Common examples:

# Standard NGINX setup for PHP framework 
nginx:
root: public_html/public
fastcgi: on
locations:
- match: /
try_files: $uri $uri/ /index.php$is_args$args
# Standard NGINX setup for Node.js via GLS
nginx:
root: public_html/public
passenger:
enabled: on
app_start_command: env PORT=$PORT node server.js
# Standard NGINX setup for Python through WSGI
nginx:
root: public_html/public
passenger:
enabled: on
python: .pyenv/shims/python
features:
- python # This install python to .pyenv/shims/python
commands:
- echo "from app import app as application" > passenger_wsgi.py

All configurations below are not preserved at each config update. It's recommended to use the NGINX tab in the dashboard to reconfigure NGINX.

fastcgi

Whether to enable or not enable PHP file execution: on, always or off. If omitted, off is the default.

tip

Read more about fastcgi option in Deployment for PHP.

error_pages

List of error pages command. It's particularly useful for static websites. Read on the NGINX docs.

  • 404 /404.html: Show 404 error page as 404.html.
  • 404 =200 /200.html: Assume 404 error as 200 OK and show 200.html (SPA).
  • 500 502 503 504 /50x.html: Show 50x error as 50x.html.

passenger

If you want to run Non-PHP apps, you need to setup with Passenger Phusion. Passenger is an additional layer on top of NGINX to run any non-PHP apps.

To enable non-PHP apps, at minimum you need these configuration:

root: public_html/public
nginx:
passenger:
# required
enabled: on
app_start_command: node server.js --port=$PORT
# optional envar setup
app_env: production # NODE_ENV
env_var_list:
- TZ=UTC

The configuration above will execute node server.js --port=$PORT in the parent of root folder (in this case, ~/public_html). Note that you always need to pass the $PORT and use that as the port where your app is listening to. If your app accept port from environment instead you can use env like env PORT=$PORT node server.js.

To restart a non-PHP apps you can execute restart in CLI/SSH. You can also make it always restart if you have to.

Available options:

  • enabled: on or off (default)
  • app_env: environment setup. Either production (default) or development.
  • env_var_list: array of environment values in the format of KEY=VALUE.
  • set_header_list: array of header values in the format of KEY=VALUE.
  • app_start_command: Passenger GLS (shell) command to start the app with $PORT as the port where your app is listening to.
  • friendly_error_pages: on (default) or off
  • base_uri: base URL for the app (default is /).
  • document_root: path to public document root (default is root) (relative to $HOME).
  • app_root: path to app root (default is parent of root) (relative to $HOME).

For non-GLS (an alternative way if not using app_start_command) these options are available too:

  • app_type: Type of App
  • startup_file: Startup filename.
  • ruby: Path to Ruby executable (relative to $HOME).
  • nodejs: Path to Node.JS executable (relative to $HOME).
  • python: Path to Python executable (relative to $HOME).
  • meteor_app_settings: Path to Meteor app settings (relative to $HOME).
tip

Read more about passenger option for general app in NGINX and App daemon.

locations

Array objects which one or more of:

  • match: Matching URL location (required)
  • root: Root path (relative to $HOME)
  • alias: Alias path (relative to $HOME)
  • rewrite: Rewrite URL directive
  • try_files: Try files URL directive
  • return: Return code directive
  • index: Index files (defaults to index.html unless fastcgi is on, then it's index.html index.php)
  • expires: Cache expiration header duration (default is 7d) can be set to 1d, off, max
  • allow : IP to allow
  • deny : IP to deny
  • autoindex: on or off (default) to enable listing directory files
  • default_type: default MIME type
  • proxy_pass: Proxy to 127.*.*.*:*
  • fastcgi: (same as above)
  • passenger: (same as above)
  • limit_except, limit_rate, limit_rate_after configure limits

Please read NGINX Location directive for more information.

commands

Type: array of string or object.

List of SSH commands in sequence. The starting directory is always ~/public_html. If any exit code detected to be not zero, the execution chain stop.

This is where all the terminal commands written, for example to install depedencies, compiling binaries or injecting database credential.

The list of commands is always executed after the source and features and before nginx.

If array item is object, it can be:

  • command: Nothing different with passing string directly
  • feature: One of feature need to be run at the sequence
  • services: One of services need to be run at the sequence
  • filename and content: Do echo $CONTENT > $FILENAME

services

Type: string or object.

Aids in compose file management for docker. If passed as string, the compose file will read from given filename. Otherwise, The services object is used as the YAML script for compose file.

Passing string as the compose filename is recommended as you can also define volumes and networks in compose file.

The compose file is read, then modified, then saved back to given filename or docker-compose.yml relative to $HOME/public_html. See docker deployment to understand how it works.

Builtin envar for commands

Aside with the usual SSH commands, it does have an additional envar to help with scripting:

  • $USERNAME: The server username.
  • $DATABASE: The database name (usually ${USERNAME}_db but can be changed if new database name is supplied before).
  • $PASSWORD: The user SSH login password.
  • $MYPASSWD: The user MariaDB login password.
  • $PGPASSWD: The user PostgreSQL login password.
  • $RDPASSWD: The user Valkey login password.
  • $DOMAIN: The domain name.

These envars also will be set and exported:

  • CI=true
  • CONTINUOUS_INTEGRATION=true
  • LANG=en_US.UTF-8
  • LC_ALL=en_US.UTF-8
  • PIP_PROGRESS_BAR=off
  • BUILDKIT_PROGRESS=plain

These shell extras also be set:

  • unset HISTFILE TERM
  • shopt -s dotglob

Time limit

The time limit for overall script in single run is 15 minutes. If it's exceeded, the execution chain will automatically stop by signaling both SIGTERM and SIGKILL.


subdomains and subdomain

subdomains is used to run specific commands for a given subdomain name. It's an array of objects with subdomain, some of the features and commands keys. Here's specific example to do it:

subdomain: mysubapp
features:
- mysql # creates mysql db for mysubapp.<domain>
subdomains: 
- subdomain: mysubapp
features:
- mysql # creates mysql db for mysubapp.<domain>
- subdomain: mysubweb
features:
- mysql # creates mysql db for mysubweb.<domain>

When subdomains are used, some definitions such as source, nginx, features and commands is adjusted to apply for a given subdomain name, including changing the root execution to ~/domains/<subdomain_name>/public_html instead of ~/public_html.