PHP Setup (Shared Hosting)
This guide describes how to set up a self-hosted instance of LiveCodes on shared hosting that supports PHP and MySQL, without installing anything on the server.
Why?
LiveCodes is a client-side app. It can be easily self-hosted on any static file server or CDN (See Self-Hosting guide).
All core functionalities (e.g. editors, compilers, formatters, code execution, etc) run in the browser. However, some features require external services which depend on server-side implementations (e.g. sharing short URLs, broadcast server, etc). The PHP setup described here provides implementations for self-hosting these services, as an alternative to the Docker setup (which requires a VPS).
This allows self-hosted instances on shared hosting to have the same features as the hosted app (livecodes.io).
Most self-hosted instances will not require this setup. The static app should work just fine using other simpler self-hosting methods. Only use the PHP setup if you need to self-host these services.
Requirements
The hosting provider should offer:
- Apache with
mod_rewriteandmod_headersenabled (typical for shared hosting) - PHP 8.0+ with PDO MySQL, cURL and mbstring extensions (all commonly available)
- MySQL (or MariaDB) database credentials
- HTTPS (TLS certificate) — usually supplied by the hosting provider
- A subdomain (e.g.
sandbox.example.com) pointing to the same hosting account, used as the separate-origin sandbox
Nothing needs to be installed on the server. The app is built in CI (GitHub Actions) and uploaded as plain files over FTP or SSH/rsync.
Getting Started
-
Fork the GitHub repo.
-
In your hosting control panel:
- Create a MySQL database user (and a database, if your provider does not allow creating databases from PHP).
- Optionally, create a subdomain for the sandbox (e.g.
sandbox.example.com) that points to the same document root as the main domain.
-
In the forked repo settings (Secrets and variables → Actions), add:
Variable
PHP_ENV:Contains all non-sensitive configuration as key=value pairs, one per line (
.envformat):HOST_NAME=example.com
SANDBOX_HOST_NAME=sandbox.example.com
SELF_HOSTED_SHARE=true
SELF_HOSTED_BROADCAST=true
FIREBASE_CONFIG={"apiKey":"..."}
LOG_URL=https://api.example.com/logKey Description HOST_NAMEHostname of the app (e.g. example.com)SANDBOX_HOST_NAMEHostname of the sandbox (e.g. sandbox.example.com)FIREBASE_CONFIG(optional) Firebase config object (JSON), used for authentication LOG_URL(optional) Full URL to send server-side analytics (e.g. https://api.website.com/log)Secrets (sensitive values only):
Secret Description MYSQL_HOSTMySQL hostname (usually localhost)MYSQL_PORTMySQL port (optional, default 3306)MYSQL_USERMySQL user MYSQL_PASSWORDMySQL password MYSQL_DATABASEMySQL database name BROADCAST_TOKENS(optional) Comma-separated list of broadcast user tokens API_TOKEN(optional) Token sent with the analytics requests Deploy using FTP:
Secret Description FTP_HOSTFTP server hostname (enables the FTP deploy job) FTP_USERFTP user FTP_PASSWORDFTP password FTP_PORTFTP port FTP_PROTOCOLFTP protocol ( ftp,ftpsorftps-legacy)FTP_PATHRemote path of the document root (e.g. /public_html/)Or deploy using SSH:
Secret Description SSH_HOSTSSH server hostname (enables the SSH/rsync deploy job) SSH_USERSSH user SSH_KEYSSH private key SSH_PORTSSH port SSH_PATHRemote path of the document root -
Push to the
mainbranch (or run the workflow manually from the Actions tab: Deploy to PHP).
The workflow builds the app, copies the PHP server files from server/php to the build directory, generates the server configuration from the secrets above, and uploads everything to your hosting over FTP and/or SSH (each job runs only when its secrets are configured and the repository variable PHP_ENV is set).
The database and required tables are created automatically on first request if they do not exist (creating the database requires the MySQL user to have the CREATE privilege; otherwise pre-create it in the hosting control panel).
Services
-
Provide project-specific meta tags, for social media cards.
-
Allows embedded representations on third party sites. See details in Embeds.
-
Adding headers
e.g. aggressive caching of static assets for improved performance (applied in
.htaccess). -
Generates a short URL that can be shared. The project config is stored in the MySQL database.
-
Broadcasts updates to connected clients. Since WebSockets are not available on shared PHP hosting, channel state is stored in the MySQL database and viewer pages poll for updates (every ~1.5 seconds). The broadcast API used by the app is identical to the other setups.
-
CORS proxy
Allows importing content from external URLs.
-
Separate origin sandbox
Runs code in a separate origin sandboxed iframe to prevent cross-site scripting. This requires a subdomain (e.g.
sandbox.example.com) pointing to the same document root; requests to the subdomain are routed to the sandbox content (setSANDBOX_HOST_NAMEaccordingly). -
Custom 404 page for resources that are not found.
Unlike the Docker setup, automatic HTTPS is not included. TLS certificates should be provided by the hosting provider (most shared hosts offer free certificates).
Deployment
The included GitHub Actions workflow deploys on push to the main branch (and can be triggered manually). The workflow only runs when the repository variable PHP_ENV is set (Settings → Secrets and variables → Actions → Variables).
Configuration is read from two sources:
PHP_ENV(repository variable): Non-sensitive config in.envformat — hostnames, feature flags, ports, Firebase config, log URL. These are used both as build-time environment variables and server runtime config.- GitHub Secrets: Sensitive values only — MySQL credentials, API tokens, broadcast tokens.
The workflow has two independent jobs:
- deploy-ftp: uploads the build using FTP (runs when
FTP_HOSTis set). - deploy-ssh: uploads the build using rsync over SSH (runs when
SSH_HOSTis set).
See Deployment for details about this workflow and the other included deploy workflows.