Guide

Shared hosting (cPanel)

A shared hosting account, such as cPanel's, often on CloudLinux, gives you a folder and a web server the host runs: Apache or LiteSpeed, sometimes with NGINX in front. It gives no root and no systemd. A Quillo program can run there behind FastCGI, with its plugins built beforehand. This page covers how, and what such an account changes. For a server of your own, see Hosting.

What is different on a shared server

On a shared accountWhat to do
127.0.0.1shared with every account on the machine: any of them can connect to a port there, past the web serverlisten on a Unix socket in a folder of your own, or answer FastCGI: never a TCP port
Processesnothing keeps one of yours running; processes started by hand or by cron are often killedlet the web server start the program: mod_fcgid starts it, keeps it up while requests come, and stops it when idle
Rustnot installedbuild the .qwer files elsewhere, upload them built, and start it with quillo fcgi main.qwe --no-build (an option, as for quillo run: see the options)
LimitsCloudLinux's LVE: processes (NPROC, which counts threads, for the whole account) and requests at once (EP; over it, visitors get a 508 page from the host)quillo fcgi main.qwe --workers 8 or so
SystemAlmaLinux, CloudLinux or CentOS 7 and 8, with old glibcthe Linux releases from 0.7.0 on, linked against glibc 2.17

The binary

The Linux releases from 0.7.0 on are linked against glibc 2.17. They start on CentOS 7, CloudLinux 7 and 8, AlmaLinux 8 and every newer system. Releases up to 0.6.0 need glibc 2.35. They are glibc builds, not static ones, because a plugin is a library the binary loads, and a static binary cannot load one.

Put quillo in a folder of the account's own, /home/u/bin/quillo, and check it starts:

/home/u/bin/quillo --version

FastCGI with mod_fcgid

mod_fcgid is in cPanel's EasyApache 4, and many shared hosts have it on. quillo fcgi main.qwe answers FastCGI on the socket the web server gives it on file descriptor 0. Apache starts it on the first request, keeps it while requests come, and stops it when idle.

Keep the program outside the public folder, in /home/u/app: its .qwe files, its .env and its database. In public_html (or the domain's folder) go two files. The first is app.fcgi, made executable with chmod 755 app.fcgi:

#!/bin/shcd /home/u/app && exec /home/u/bin/quillo fcgi main.qwe --no-build --workers 8

The second is .htaccess, which sends every request that is not a file there to it:

Options +ExecCGIAddHandler fcgid-script .fcgiRewriteEngine OnRewriteCond %{REQUEST_FILENAME} !-fRewriteRule ^ app.fcgi [QSA,L]

Run from a terminal, quillo fcgi says what it needs:

quillo: file descriptor 0 is not a socket: `quillo fcgi` is started by a FastCGI process manager (mod_fcgid), or given --listen unix:PATH or --port

On a server of your own, quillo fcgi main.qwe --listen unix:f.sock makes its own socket. It is short and relative to the folder quillo runs in, as a socket's path is at most 100 bytes. Then nginx passes requests to it:

location / {    include fastcgi_params;    fastcgi_pass unix:/srv/app/f.sock;}

A Unix socket behind mod_proxy

Where the host sets it up (a VPS with WHM, or a host that offers Quillo), the program can run as a server on a Unix socket, with Apache proxying to it:

quillo run main.qwe --listen unix:app.sock --trust-proxy 127.0.0.1
ProxyPass "/" "unix:/home/u/app/app.sock|http://localhost/" upgrade=websocketProxyPassReverse "/" "http://localhost/"

upgrade=websocket needs Apache 2.4.47 or later. ProxyPass belongs in the host's configuration, not in .htaccess.

Plugins, built beforehand

The account has no Rust, and a build on the server would run each crate's build scripts there.

  1. Build the program's .qwer files with quillo build main.qwe on Linux, on the same processor as the server. Use a system no newer than the server's: a plugin linked against a newer glibc does not load on an older one. A CentOS 7 or AlmaLinux 8 container works.
  2. Upload .quillo/ with the program. It holds .quillo/native/, the libraries, and .quillo/plugins.lock, each library's SHA-256.
  3. Run with --no-build. Nothing is built on the server. A library that is not the one the lock names is refused rather than built again:
quillo: will not load the library of ./hi.qwer: libhi-d7fb9105-g2-687dd0b24f29e5cf.so is not the library that was built (its SHA-256 differs from .quillo/plugins.lock's); build it with `quillo build`, which writes the lock, and bring .quillo along

A library is named by its file's whole name (so hi.rs and hi.qwer keep one each), the glue's version and a hash of the file's text. A new quillo whose glue changed loads none of the libraries an older one built: run quillo build main.qwe with it once, as part of the deploy that brings it, and upload .quillo/ again. Until then the server says so:

quillo: ./hi.qwer was built by an older Quillo, whose libraries this one cannot load, and --no-build says not to build it here: run `quillo build` once where Rust is, and bring .quillo along

A plugin called inside a with function needs a //! effects: line in its header. A plugin without one may do anything, so it is refused there (see Rust).

A policy

The host's /etc/quillo/policy.toml says what any program on the server may do. A quillo.policy beside the program narrows it for the site. Each file only takes away:

# quillo.policy, beside main.qwe[plugins]build = falseallow = ["csv@1", "qr"][http]private = falsehosts = ["api.stripe.com"][env]names = ["QUILLO_SECRET", "DATABASE_URL"][limits]workers = 8

A limit takes what its option takes: workers = 0 is refused (p.toml:2: `workers` is a positive number, as `--workers` takes), and so is a max_body or max_compute of 0. The start line lists the limits that hold the program: quillo: policy quillo.policy (workers 8). A request the policy's max_compute ends is a 500, as one --max-compute ends, wherever it is ended (a loop, a call, highlight, markdown), and the log names whichever is the tighter (this request computed for longer than the policy p.toml allows (max_compute), or ... than --max-compute allows). No ?? takes that stop, highlight(x) ?? x included. A page is told the server's policy, with no path of the server's.

quillo check --policy policy.toml main.qwe, run before uploading, says what the program would be refused. The sections and what each does are in The policy.

A policy binds the quillo that reads it. On a shared server, a user who can upload a binary of their own can run it without one: the boundary between accounts is the system's (Unix users, CloudLinux's CageFS and LVE limits).

Threads and ulimit -u

A Quillo server may use --workers + 9 threads: 73 with the default of 64. On Linux, the account's process limit counts threads, beside PHP, cron and SSH. Give --workers 8 or so; a host's policy can cap it with [limits] workers.

At start, a server says when ulimit -u is below what it may use:

quillo: the process limit (ulimit -u) is 30, and this server may use 73 threads: requests may wait for a thread; raise it, or give --workers fewer

A thread the system refuses later is said once, and the requests wait for the threads there are.

The rest of the account

Before going live

Thread
6Useful? Like it, or add to its thread below.

Thread 0 posts

On Shared hosting (cPanel): questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.