# Stacks: deploy guides for Node, Python, PHP and Java Deploy guides for every stack ox runs: React, Next.js, Django, Rails, Laravel, Spring Boot and more, each with its plan and proof, filterable by language. Pick your stack to deploy it to your own VPS with ox. Each guide shows the plan `ox check` prints for a minimal repo of that stack, the ox.toml if you need one, the variables to set, and the messages you see when a deploy fails. The badge says how far it is proven. Three of the guides, drawn from their own ox.toml: what ox starts or serves for each. Each guide's file goes through the same checks as `ox check`, which says `Ready to deploy.` for every one. - **Tested on a real server:** an app of this stack deployed and served on a real Ubuntu server in ox's test lab. - **Plan verified, real-server test pending:** ox's tests pin the plan it makes for the stack, and no real-server deploy is recorded yet. ## All stack guides Filter by language, or read by kind of app. A simple repo needs no ox.toml at all, so the [Quickstart](https://console.t57.sorv.dev/docs/quickstart) is the shortest path for any of them. - [All](https://console.t57.sorv.dev/docs/guides#lang-all) - [JavaScript and TypeScript](https://console.t57.sorv.dev/docs/guides#lang-js) - [Python](https://console.t57.sorv.dev/docs/guides#lang-python) - [Ruby](https://console.t57.sorv.dev/docs/guides#lang-ruby) - [PHP](https://console.t57.sorv.dev/docs/guides#lang-php) - [Java](https://console.t57.sorv.dev/docs/guides#lang-java) - [C# and .NET](https://console.t57.sorv.dev/docs/guides#lang-dotnet) - [Elixir](https://console.t57.sorv.dev/docs/guides#lang-elixir) - [Rust](https://console.t57.sorv.dev/docs/guides#lang-rust) ### Static sites and single-page apps ox runs the build and Caddy serves the files over HTTPS. No app process runs. - [**Deploy a static site** Deploy a Vite single-page app, an Astro site or plain HTML to your own VPS. Caddy serves the files over HTTPS, no app process, with a tiny ox.toml or none. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/static-site) - [**React with Vite** Deploy a React app built with Vite to your own VPS with no Dockerfile: ox runs the build from your lockfile and Caddy serves dist over HTTPS, no ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/react-vite) - [**Create React App** Deploy a Create React App project to your own VPS: ox runs react-scripts build and Caddy serves the build folder over HTTPS. No Docker, no ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/create-react-app) - [**Vue CLI** Deploy a Vue CLI app to your own VPS: ox installs from yarn.lock, runs your build, and Caddy serves dist over HTTPS. The plan comes from the repo alone. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/vue) - [**Angular** Deploy an Angular single-page app to your own VPS: ox reads the output folder from angular.json, runs ng build, and Caddy serves it, with no Docker. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/angular) - [**Next.js static export** Deploy a Next.js app with output: 'export' to your own VPS: ox runs next build and Caddy serves the out folder over HTTPS, with no Node process running. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/nextjs-static-export) - [**Gatsby** Deploy a Gatsby site to your own VPS: ox reads gatsby-config.js, runs gatsby build from package.json, and Caddy serves the public folder over HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/gatsby) - [**Docusaurus** Deploy a Docusaurus documentation site to your own VPS: ox runs the build from package.json and Caddy serves the build folder over HTTPS, no ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/docusaurus) - [**Astro** Deploy an Astro static site to your own VPS: ox reads astro.config.mjs, runs astro build, and Caddy serves dist over HTTPS with no app process running. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/astro) - [**SvelteKit static** Deploy a SvelteKit site built with adapter-static to your own VPS: ox reads the pages folder from svelte.config and Caddy serves it over HTTPS, no Docker. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/sveltekit-static) - [**React Router SPA** Deploy a React Router 7 app with ssr: false to your own VPS: ox reads react-router.config.ts, builds it, and Caddy serves build/client over HTTPS, no Node. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/react-router-spa) ### Server-rendered JavaScript apps ox builds the app and runs its server under systemd, with Caddy in front. - [**Deploy Next.js** Self-host Next.js on your own VPS without Vercel or Docker: next start, a health check, PostgreSQL, Prisma migrations and the image cache, in one ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/nextjs) - [**Angular SSR** Deploy an Angular app with server-side rendering to your own VPS: ox builds it, runs the server.mjs Angular writes under systemd, and Caddy adds HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/angular-ssr) - [**Astro SSR** Deploy an Astro app with the @astrojs/node adapter to your own VPS: ox builds it, runs dist/server/entry.mjs under systemd, with Caddy and HTTPS in front. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/astro-ssr) - [**SvelteKit** Deploy a SvelteKit app with adapter-node to your own VPS: ox reads svelte.config.js, builds it, runs node build under systemd, and Caddy adds HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/sveltekit) - [**Nuxt** Deploy a Nuxt app with server-side rendering to your own VPS: ox runs nuxt build, starts .output/server/index.mjs under systemd, and Caddy adds HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/nuxt) - [**React Router** Deploy a React Router 7 app (the Remix successor) with server rendering to your own VPS: ox builds it, runs npm start under systemd, and Caddy adds HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/react-router) - [**SolidStart** Deploy a SolidStart app to your own VPS: ox reads the Node version from package.json, runs the build, starts it under systemd and adds HTTPS with Caddy. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/solidstart) - [**Qwik City** Deploy a Qwik City app with its Express adapter to your own VPS: ox finds the adapter, builds it, runs npm run serve under systemd, and Caddy serves HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/qwik) - [**Deno Fresh** Deploy a Deno Fresh app to your own VPS: ox installs Deno 2, runs deno install and deno task build, then deno serve under systemd with Caddy for HTTPS. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/deno-fresh) ### Full-stack web frameworks The framework's own server, its migrations and its database, from the repo. - [**Deploy Django** Deploy Django to your own VPS without Docker: gunicorn, PostgreSQL, migrations, static files served by Caddy, uploads kept across deploys, in one ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/django) - [**Deploy Rails** Deploy Rails 8 to your own VPS without Docker or Kamal: precompiled Ruby, gems, assets, db:prepare and Solid Cache, Queue and Cable on PostgreSQL. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/rails) - [**Deploy Laravel** Deploy Laravel to your own Ubuntu VPS: PHP from apt, Composer, a Vite build, PostgreSQL, a queue worker and the scheduler every minute, from one ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/laravel) - [**Symfony** Deploy Symfony to your own VPS: ox runs composer install for prod, Doctrine migrations and FrankenPHP under systemd, and asks for APP_SECRET first. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/symfony) - [**Plain PHP** Deploy a plain PHP site to your own VPS: ox finds index.php, installs FrankenPHP, and serves the site under systemd behind Caddy with HTTPS, no ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/php) - [**Phoenix** Deploy an Elixir Phoenix app to your own VPS: ox builds a mix release with its assets, runs Release.migrate, starts it under systemd, and adds PostgreSQL. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/phoenix) ### APIs, backends and workers A long-running server or worker, with the database it uses. - [**Deploy a Node API** Deploy an Express, Fastify or other Node.js API to your own VPS: start script, lockfile install, migrations, PostgreSQL and Redis, from one short ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/node) - [**Deploy FastAPI** Deploy FastAPI to your own VPS: ox detects the uvicorn start command, installs from uv.lock, runs Alembic migrations, and adds PostgreSQL from one ox.toml. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/fastapi) - [**NestJS** Deploy a NestJS API to your own VPS: ox installs from package-lock.json, runs nest build and start:prod under systemd, and sets up PostgreSQL for the app. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/nestjs) - [**Fastify** Deploy a Fastify API to your own VPS: ox finds server.js, runs node server.js under systemd behind Caddy, and adds PostgreSQL with DATABASE_URL set. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/fastify) - [**Hono on Bun** Deploy a Hono API on Bun to your own VPS: ox installs Bun, runs bun install from bun.lock, and starts src/index.ts under systemd behind Caddy. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/hono-bun) - [**BullMQ worker** Deploy a Node app with a BullMQ queue to your own VPS: ox adds Redis with REDIS_URL set, runs your server, and the [workers] line runs worker.js beside it. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/bullmq-worker) - [**Flask** Deploy a Flask app to your own VPS: ox installs with uv from requirements.txt, runs gunicorn app:app under systemd behind Caddy, and adds PostgreSQL. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/flask) - [**Spring Boot (Maven)** Deploy a Spring Boot app built with Maven to your own VPS: ox builds the jar with mvnw, installs Java 21, runs it under systemd and adds PostgreSQL for it. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/spring-boot) - [**Spring Boot (Gradle)** Deploy a Spring Boot app built with Gradle to your own VPS: ox runs gradlew bootJar, reads the Java version from build.gradle.kts, and runs the jar. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/spring-boot-gradle) - [**Quarkus** Deploy a Quarkus app to your own VPS in JVM mode: ox builds it with mvnw, runs quarkus-run.jar under systemd, checks /q/health and adds PostgreSQL for it. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/quarkus) - [**ASP.NET Core** Deploy an ASP.NET Core app to your own Linux VPS: ox installs the .NET 10 SDK, runs dotnet publish, starts the DLL under systemd, and adds PostgreSQL. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/aspnet-core) - [**Rust** Deploy a Rust web app from a Cargo workspace to your own VPS: ox installs stable Rust, runs cargo build --release --locked, and starts the binary. *Tested on a real server*](https://console.t57.sorv.dev/docs/guides/rust) ## More stacks ox has deployed or detected These have no page of their own yet. Each links to the page to start from. - [Django with Celery and Redis](https://console.t57.sorv.dev/docs/guides/django) *Tested on a real server* - [Node API and SPA in one repo](https://console.t57.sorv.dev/docs/guides/node) *Tested on a real server* - [Vue with Vite on Bun](https://console.t57.sorv.dev/docs/guides/static-site) *Tested on a real server* - [Go (net/http or Gin) with Postgres and Redis](https://console.t57.sorv.dev/docs/config#detection) *Tested on a real server* - [Python bot or worker with no web process](https://console.t57.sorv.dev/docs/config#workers) *Tested on a real server* - [Django ASGI (uvicorn or daphne) with Redis](https://console.t57.sorv.dev/docs/guides/django) *Tested on a real server* - [FastAPI with Redis, a worker and cron](https://console.t57.sorv.dev/docs/guides/fastapi) *Tested on a real server* - [Django with pgvector](https://console.t57.sorv.dev/docs/guides/django) *Tested on a real server* - [Python with Qdrant](https://console.t57.sorv.dev/docs/guides/fastapi) *Tested on a real server* - [FastAPI with Neo4j](https://console.t57.sorv.dev/docs/guides/fastapi) *Tested on a real server* - [CPU model inference (FastAPI and a Hugging Face model)](https://console.t57.sorv.dev/docs/guides/fastapi) *Tested on a real server* - [Playwright with headless Chromium (x64, Playwright below 1.61)](https://console.t57.sorv.dev/docs/config#build) *Tested on a real server* - [WordPress with MariaDB (needs an ox.toml)](https://console.t57.sorv.dev/docs/config#services) *Tested on a real server* - [Go Fiber, Echo or Chi](https://console.t57.sorv.dev/docs/config#detection) *Plan verified, real-server test pending* - [Strapi with Postgres](https://console.t57.sorv.dev/docs/guides/node) *Plan verified, real-server test pending* - [Hono on Node](https://console.t57.sorv.dev/docs/guides/node) *Plan verified, real-server test pending* - [Koa](https://console.t57.sorv.dev/docs/guides/node) *Plan verified, real-server test pending* - [Rust Actix Web](https://console.t57.sorv.dev/docs/guides/rust) *Plan verified, real-server test pending* - [Rust Rocket](https://console.t57.sorv.dev/docs/guides/rust) *Plan verified, real-server test pending* - [Eleventy](https://console.t57.sorv.dev/docs/guides/static-site) *Plan verified, real-server test pending* - [Payload CMS on Next.js](https://console.t57.sorv.dev/docs/guides/nextjs) *Plan verified, real-server test pending* - [Wagtail](https://console.t57.sorv.dev/docs/guides/django) *Plan verified, real-server test pending* - [Jekyll](https://console.t57.sorv.dev/docs/config#static) *Plan verified, real-server test pending* ## Works with an ox.toml, not yet tested ox does not detect these yet, and no test has deployed them. Write the start, build and services in an ox.toml, and check it with `ox check` first. - [Express with MySQL (mysql2)](https://console.t57.sorv.dev/docs/config#services) - [Streamlit](https://console.t57.sorv.dev/docs/config#app) - [Gradio](https://console.t57.sorv.dev/docs/config#app) - [Django with MariaDB (mysqlclient)](https://console.t57.sorv.dev/docs/config#services) - [Rails with Sidekiq and Redis](https://console.t57.sorv.dev/docs/config#workers) - [Rails with Solid Queue](https://console.t57.sorv.dev/docs/config#workers) - [Laravel with a queue worker and the scheduler](https://console.t57.sorv.dev/docs/guides/laravel) - [Express in TypeScript (tsc to dist)](https://console.t57.sorv.dev/docs/config#app) - [Hugo](https://console.t57.sorv.dev/docs/config#static) - [Telegram or Discord bot in Node](https://console.t57.sorv.dev/docs/config#workers) - [Kotlin Ktor](https://console.t57.sorv.dev/docs/config#build) - [n8n](https://console.t57.sorv.dev/docs/config#app) - [Uptime Kuma](https://console.t57.sorv.dev/docs/config#app) - [Express with SQLite (better-sqlite3)](https://console.t57.sorv.dev/docs/config#app) - [Flask with SQLite](https://console.t57.sorv.dev/docs/config#app) - [Go with SQLite](https://console.t57.sorv.dev/docs/config#app) - [Rust full-stack (Leptos or Dioxus)](https://console.t57.sorv.dev/docs/config#build) - [Bun with Elysia](https://console.t57.sorv.dev/docs/config#app) - [TanStack Start](https://console.t57.sorv.dev/docs/config#app) - [MkDocs or VitePress](https://console.t57.sorv.dev/docs/config#static) - [Directus](https://console.t57.sorv.dev/docs/config#app) - [Medusa](https://console.t57.sorv.dev/docs/config#app) - [Sinatra or Roda](https://console.t57.sorv.dev/docs/config#app) - [Hanami](https://console.t57.sorv.dev/docs/config#app) - [Odoo](https://console.t57.sorv.dev/docs/config#app) - [Drupal](https://console.t57.sorv.dev/docs/config#app) - [Slim PHP API](https://console.t57.sorv.dev/docs/config#app) - [CodeIgniter](https://console.t57.sorv.dev/docs/config#app) - [Laravel with Inertia (Vue or React)](https://console.t57.sorv.dev/docs/guides/laravel) - [Blazor Server](https://console.t57.sorv.dev/docs/config#build) - [Scala Play](https://console.t57.sorv.dev/docs/config#build) - [Clojure Ring](https://console.t57.sorv.dev/docs/config#build) - [Elixir Plug or Bandit without Phoenix](https://console.t57.sorv.dev/docs/config#build) - [Gleam](https://console.t57.sorv.dev/docs/config#build) - [Zig HTTP server](https://console.t57.sorv.dev/docs/config#build) - [C or C++ binary](https://console.t57.sorv.dev/docs/config#build) - [Dart (Shelf or Serverpod)](https://console.t57.sorv.dev/docs/config#build) ## Not supported - **Express with MongoDB:** ox runs no MongoDB: Ubuntu 26.04 has no MongoDB server package. Use a hosted one and set its URL as a variable. - **Ghost:** Ghost needs MySQL 8, and ox ships MariaDB. - **Meteor:** Meteor needs MongoDB, which ox does not run. - **Swift Vapor:** No Swift toolchain for Ubuntu 26.04 is verified yet. - **Puppeteer worker:** ox skips Puppeteer's Chrome download and installs none of its system packages, and Ubuntu 26.04's own Chromium is a snap, which ox does not run. - **GPU inference (vLLM, Ollama on a GPU):** ox does not manage GPUs or their drivers. - **Docker Compose app:** ox runs apps without Docker, by design. - **Windows, IIS or .NET Framework:** ox runs on Ubuntu only. Your stack is not here? The [detection rules](https://console.t57.sorv.dev/docs/config#detection) and the [config examples](https://console.t57.sorv.dev/docs/config#examples) cover more, and [Troubleshooting](https://console.t57.sorv.dev/docs/troubleshooting) lists the messages every deploy can print. Last updated 2026-10-09. The page as HTML: https://console.t57.sorv.dev/docs/guides