cploy is a self-hosted platform for building and publishing Vite + React applications from Git repositories. It prepares an isolated deployment directory, builds the application in Docker, serves the static result with an Nginx container, and places an Nginx reverse proxy in front of the container.
This README covers the project, local development, deployment host setup, and operations.
- Authenticates users and keeps deployment records in SQLite.
- Allocates an available host port for every active deployment.
- Validates app names before deployment work begins.
- Clones a repository's
mainbranch into a dedicated deployment directory. - Builds the Vite application in a multi-stage Docker image.
- Serves the built static files from Nginx inside a container.
- Creates a host-level Nginx reverse-proxy configuration for the app subdomain.
- Supports per-deployment environment variables through a generated
.envfile. - Removes the container, proxy configuration, and deployment files when a deployment is deleted.
Browser
│
▼
Host Nginx ──► app-name.dev-saurabh-k.xyz
│ │
│ ▼
│ Docker container
│ │
│ ▼
│ Nginx (static Vite build)
│
▼
cploy service ──► SQLite deployment records
│
├──► Git repository checkout
├──► Docker Compose build and startup
└──► Host Nginx configuration
| Path | Purpose |
|---|---|
main.py |
Application entry point and CORS configuration. |
auth.py |
Password hashing and token authentication configuration. |
models.py |
SQLite data models for users and deployments. |
routes/ |
Application request handling. |
services/deploy_service.py |
Background deployment and deletion orchestration. |
scripts/ |
Linux deployment, Docker Compose, repository, and Nginx automation. |
templates/Dockerfile |
Universal multi-stage Docker build for deployed Vite apps. |
templates/nginx.conf |
Nginx configuration installed inside each application container. |
sample/ |
Example Vite + React applications. |
- Python 3.10 or later
pip- Git
- Linux host with Bash
- Docker Engine with the Docker Compose plugin (
docker compose) - Git
- Nginx installed and enabled
- A DNS wildcard or individual DNS records pointing app subdomains to the host
- Permission for the service user to manage Docker and reload Nginx
- A directory in which deployments can be created (the current scripts use
/opt/deployCode)
-
Clone the repository and enter it.
git clone <your-repository-url> cd cploy
-
Create and activate a virtual environment.
python -m venv .venv
On macOS or Linux:
source .venv/bin/activateOn Windows PowerShell:
.venv\Scripts\Activate.ps1
-
Install dependencies.
pip install -r requirements.txt
-
Start the service for local development.
uvicorn main:app --reload
SQLite creates cploy.db automatically in the working directory. It is
ignored by Git so local data is not committed.
The scripts are designed to run on the Linux deployment host. Review and adapt the paths and domain before using them outside the current environment.
The scripts currently reference the project templates at:
/home/saurabh/deployCode/templates
and create deployed applications at:
/opt/deployCode/<app-name>
If your checkout lives elsewhere, update the absolute template paths in
scripts/create_deployment_dir.sh and the script paths in
services/deploy_service.py together.
The host Nginx script currently creates sites for:
<app-name>.dev-saurabh-k.xyz
Change this domain in both scripts/setup_nginx.sh and
services/deploy_service.py if you use another domain. Ensure the matching DNS
record resolves to the deployment host.
The service account needs permission to:
- Run Docker and Docker Compose.
- Write deployment directories under
/opt/deployCode. - Create and enable Nginx site configurations.
- Test and reload Nginx.
Use narrowly scoped sudoers rules when the application runs under a service
account. Do not grant unrestricted root access merely to run deployments.
Before production use, replace the hard-coded token signing key in auth.py
with a securely managed environment variable. Keep the production database,
deployment .env files, and generated Nginx configurations readable only by
the appropriate host users.
Each deployment is processed in the background and follows this sequence:
- Validate the app name and confirm no active deployment already uses it.
- Reserve an available port.
- Create
/opt/deployCode/<app-name>. - Copy the universal
Dockerfileand container Nginx configuration into that directory. - Generate
.envanddocker-compose.yml. - Initialize the deployment directory as a Git checkout and pull the
repository's
mainbranch. - Run
docker compose up -d --buildin the deployment directory. - Configure the host Nginx reverse proxy and reload Nginx.
If a step fails, the deployment record is marked as failed and includes an error message for troubleshooting.
An app name is used as the deployment directory name, Docker container name, and subdomain. Names must therefore be:
- 1 to 63 characters long
- Lowercase
- Started with a letter
- Made from lowercase letters, digits, and internal hyphens only
- Unique among active deployments, including deployments owned by other users
Examples: portfolio, shop2, and my-app are valid. MyApp, my_app,
-app, and app- are not valid.
Deployment-specific variables are passed to the deployment workflow and written to:
/opt/deployCode/<app-name>/.env
The generated Compose file references this file with env_file: .env, making
the variables available to the running container. Variable names must start
with a letter or underscore and may contain only letters, digits, and
underscores. Values cannot contain line breaks. A maximum of 100 variables is
allowed for one deployment.
Vite replaces VITE_* values while npm run build is running. The generated
Compose .env file is loaded when the finished Nginx container starts, so it
does not by itself change values already bundled into a static Vite build. Use
build arguments and matching Dockerfile ARG/ENV instructions if a deployed
Vite application needs configuration embedded at build time.
templates/Dockerfile uses two stages:
- A Node image installs dependencies and runs the Vite build.
- An
nginx:alpineimage serves the resultingdistdirectory.
The deployment setup copies templates/nginx.conf beside the Dockerfile. The
Dockerfile installs it as:
/etc/nginx/conf.d/default.conf
That configuration provides SPA fallback (/index.html) so client-side routes
continue to work when loaded directly.
scripts/setup_nginx.sh creates a server block under
/etc/nginx/sites-available, enables it with a symlink in
/etc/nginx/sites-enabled, tests the Nginx configuration, then reloads Nginx.
The proxy forwards the app subdomain to the port allocated to its Docker
container.
On the deployment host, inspect the application files, generated Compose
configuration, and .env file at:
/opt/deployCode/<app-name>
From that deployment directory:
docker compose ps
docker compose logsFrom the same directory:
docker compose up -d --buildsudo nginx -t
sudo systemctl status nginx| Symptom | Likely cause | Suggested check |
|---|---|---|
| Container fails to build | Repository is not a compatible Vite project or dependencies fail to install | Inspect docker compose logs and the repository's package.json. |
| App subdomain does not resolve | DNS record is missing or points to the wrong host | Verify DNS and the configured base domain. |
| Nginx fails to reload | Invalid generated or existing Nginx configuration | Run sudo nginx -t and inspect the named site file. |
| Compose cannot start | Docker is unavailable or the assigned port is occupied outside cploy | Check Docker service status and host port usage. |
| Environment variable is unavailable in the browser | Static Vite values are fixed at build time | Use build-time configuration rather than only Compose runtime variables. |
The sample/ directory contains small Vite + React projects for testing the
container build. They are useful for verifying a deployment host before using a
production repository.
cploy is tailored to its current self-hosted deployment environment. Before exposing it publicly, review authentication secret management, host permissions, rate limiting, logging, database backups, and deployment isolation for your own security and reliability requirements.