[Blog](https://deploywithox.com/blog) [Guides](https://deploywithox.com/blog#c-guides) # How to self-host Quickwit on your own VPS without Docker Run Quickwit 0.9.1, the open-source log search engine, on your Ubuntu server with ox and no Docker: a Rust build and Postgres, from the config that ran. Saurav Sharma Oct 17, 2026 9 min read On this page - [What you need](https://deploywithox.com/blog/self-host-quickwit#what-you-need) - [The steps to install Quickwit on Ubuntu](https://deploywithox.com/blog/self-host-quickwit#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-quickwit#config) - [Postgres, updates and backups](https://deploywithox.com/blog/self-host-quickwit#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-quickwit#faq) To self-host Quickwit you need an Ubuntu server, a fork of the Quickwit repo with one `ox.toml` file added, and no variables to set. In our run the first deploy took about 23 minutes, most of it compiling Quickwit's Rust code, and ox set up the Postgres database where Quickwit keeps its index records. **How we tested** On Oct 17, 2026, ox deployed Quickwit v0.9.1 from commit [`962685f5`](https://github.com/quickwit-oss/quickwit/commit/962685f5a334f6c9d8516d2d7c1fdd08891b687c) on a fresh DigitalOcean server with 8 vCPUs and 16 GB of memory. The run then redeployed it, backed it up and rebooted the server. Then a separate test agent, one that did not write the config, used the API to make an index, add a document and find it by search, in the API and in the web UI, and checked the app's services and its backup. [Quickwit](https://github.com/quickwit-oss/quickwit) is an open-source search engine for logs and traces. You make an index, send it JSON documents and search them with a query language through a REST API. Its README also lists an Elasticsearch-compatible API and OpenTelemetry and Jaeger support. The code is Apache 2.0, written in Rust, and builds into one binary with a web UI inside. The UI at `/ui/` has a Query editor and pages for indexes, the cluster and the node. It is for looking. You make indexes and add documents through the API. ox deployed Quickwit v0.9.1 (commit 962685f5) on Oct 17, 2026 on a fresh DigitalOcean server with 8 vCPUs and 16 GB of memory; the first deploy took 23 minutes and a redeploy took 13 minutes. - **First deploy:** 23 minutes, from adding the project until the app passed the run's first checks. - **Redeploy of the same commit:** 13 minutes, until the app passed the checks again. - **Server:** DigitalOcean, 8 vCPUs and 16 GB of memory (`s-8vcpu-16gb`), with this app alone on it. Every one of the 85 apps we deployed ran on this one size, so it was not picked for this app. - **Memory in use after the reboot:** 688 MB of 15986 MB, for the whole server: Ubuntu, the app, its services, Caddy and the ox agent. On a server with no apps, ox's tests on real servers hold the agent to 40 MB or less and Caddy to 50 MB or less. - **Services ox runs for it:** `postgres`. - **Source:** [github.com/quickwit-oss/quickwit](https://github.com/quickwit-oss/quickwit) at v0.9.1, commit [`962685f5`](https://github.com/quickwit-oss/quickwit/commit/962685f5a334f6c9d8516d2d7c1fdd08891b687c). ## What you need - An Ubuntu LTS server. The run used the size in the facts above and measured the memory there. The server compiles Quickwit itself, so it reaches the internet for Cargo crates and npm packages. - A GitHub account to fork `quickwit-oss/quickwit`, and an ox account, which you open by signing in with GitHub. - No outside account. The run kept the index files on the server's disk. Cloud storage for indexes, log shippers, the OpenTelemetry, Jaeger and Elasticsearch-compatible endpoints and sources such as Kafka were not tested. ## The steps to install Quickwit on Ubuntu In the ox dashboard press Add a server and run the command it shows as root on your Ubuntu machine. It installs the ox agent and Caddy. Fork `quickwit-oss/quickwit` and start from commit `962685f5`, titled Release 0.9.1, the one the run deployed. Add the `ox.toml` shown below at the top of the repo, then commit and push. The config asks for no variables, so there is no env file. With the [ox CLI](https://deploywithox.com/docs/cli) signed in, run: Shell ```bash ox new /quickwit ox review quickwit ox deploy quickwit --wait ``` The project takes the repo's name. `ox review` prints the plan and exits 0 when nothing is left to answer. `ox deploy --wait` streams the first deploy to its end. The [quickstart](https://deploywithox.com/docs/quickstart) shows the same steps in the browser. When the deploy is green, open the address ox shows. It redirects to the UI's Query editor. The run used this preview address, and a domain of your own was not tested. The [domains page](https://deploywithox.com/docs/operate/domains) covers adding one. Quickwit has no sign-in, so the test agent went straight to the API: Shell ```bash SITE=https:// curl -s $SITE/health/readyz curl -s $SITE/api/v1/version curl -s -X POST $SITE/api/v1/indexes -H 'Content-Type: application/json' \ --data '{"version":"0.9","index_id":"verifynotes","doc_mapping":{"field_mappings":[{"name":"body","type":"text"}]}}' curl -s -X POST "$SITE/api/v1/verifynotes/ingest?commit=force" \ -H 'Content-Type: application/json' --data-binary '{"body":"hello quickwit from the verifier"}' curl -s "$SITE/api/v1/verifynotes/search?query=body:quickwit" ``` The readiness route answers 200 with `true`, and the version route reports 0.9.1. The ingest call reports `num_ingested_docs` 1, and the search returns the document with `num_hits` 1. The Query editor finds it too: pick the index, type `body:quickwit` and press Run. The Indexes page also lists `otel-logs-v0_9` and `otel-traces-v0_9`, which Quickwit made itself at its first start. The test agent added `commit=force`, which commits at once. Without it a new document is searchable only after its split commits, by default up to 60 seconds later. Quickwit has no accounts or keys, so anyone who has the project's address can use the API. The run put nothing in front of it. ## The ox.toml, line by line TOML ```toml # Quickwit 0.9.1, one node: the REST API and the UI on $PORT, the # metastore in the project's postgres, the index files in the kept folder. # The build follows the repo's Dockerfile (UI first, embedded into the # binary, then cargo with the release feature set). packages = ["clang", "llvm", "cmake", "pkg-config", "protobuf-compiler", "libssl-dev"] [app] # QW_DATA_DIR is the kept folder's stable place, not the release's link to # it: the metastore records each index's absolute path, and a release folder # is pruned three deploys later. gRPC defaults to REST+1, which can be the # next project's port; 7281 is Quickwit's own default and outside ox's range. start = 'export QW_LISTEN_ADDRESS=127.0.0.1 QW_REST_LISTEN_PORT="$PORT" QW_GRPC_LISTEN_PORT="${QW_GRPC_LISTEN_PORT:-7281}" QW_DATA_DIR="$OX_DATA_DIR/qwdata" QW_METASTORE_URI="$DATABASE_URL"; exec .ox/bin/quickwit run --config config/quickwit.yaml' health = "/health/readyz" # One data folder, one WAL and one fixed gRPC port: two nodes at once # would fight over them. stop_before_start = true [build] install = "" # The target folder lives in HOME so a redeploy rebuilds only Quickwit's # own crates, and the release keeps the binary alone. commands = [ "cd quickwit/quickwit-ui && touch .gitignore_for_build_directory && NODE_ENV=production make install build", "cd quickwit && CARGO_TARGET_DIR=\"$HOME/.cache/quickwit-target\" cargo build -p quickwit-cli --features release-feature-set --bin quickwit --release", "mkdir -p .ox/bin && cp \"$HOME/.cache/quickwit-target/release/quickwit\" .ox/bin/quickwit && .ox/bin/quickwit --version", ] migrate = "" [services] postgres = {} [storage] keep = ["qwdata"] [tools] rust = "1.96" node = "24" yarn = "1.22.22" ``` The file follows the repo's Dockerfile: the UI first, embedded in the binary, then Cargo with the release feature set. - `packages` lists the Dockerfile's build tools (clang, llvm, cmake, protobuf-compiler, libssl-dev) plus pkg-config. - `start` sets five Quickwit variables and runs the built binary with `exec`, so ox's stop signal reaches it. `quickwit run` starts every service in one process, using the repo's own `config/quickwit.yaml`. - The listen address stays on loopback, where only Caddy reaches it, and the REST port is the `$PORT` ox hands out, so the API and the UI answer there. - The gRPC port would default to the REST port plus one, which on a shared server can be another project's port. The line fixes 7281 instead, Quickwit's usual gRPC port and outside the range ox hands out. - `QW_DATA_DIR` is the project's data folder. Quickwit records each index's absolute path in its metastore, and ox deletes old release folders, so the data cannot live inside a release. - `QW_METASTORE_URI` keeps the metastore, Quickwit's record of its indexes, in the project's Postgres. - `health` is Quickwit's readiness route. ox switches to a new release only after it answers. - `stop_before_start` is on because one data folder, one write-ahead log and one gRPC port cannot serve two copies. Each redeploy has a short gap while the old copy stops. The first deploy has none. - `install = ""` skips ox's own install step, since the build commands do the installing. - The first build command is the Dockerfile's UI step. Yarn installs from the frozen lockfile and builds the UI into the folder that Quickwit's Rust code embeds. The `touch` makes a file the UI's build script copies. - The second runs `cargo build` with `release-feature-set`, which includes the Postgres metastore. It runs in the `quickwit` folder so Cargo reads `.cargo/config.toml` and its `tokio_unstable` flag. `CARGO_TARGET_DIR` sits in the project's home, so a redeploy rebuilds only Quickwit's own crates. - The third copies the binary to `.ox/bin` and prints its version. - `migrate` is empty because Quickwit creates and updates its own Postgres tables at start. - `[services]` asks for Postgres, the metastore's database. `[storage]` keeps `qwdata`, so the data folder survives deploys and goes into backups. - `[tools]` pins Rust 1.96 (the repo's `rust-toolchain.toml`), Node 24 (the Dockerfile's UI stage) and Yarn 1.22.22 (the UI's `package.json`). There are no workers or cron jobs. Indexing, merging and clean-up run in the one process, the only unit the run's check found. This config asks for no variables. ox provides the three values the start line reads: `PORT`, `OX_DATA_DIR` and `DATABASE_URL`, which comes from the Postgres service. That is why the review had nothing to ask. `QW_GRPC_LISTEN_PORT` is the one name you could set yourself, and the run set none. See [variables](https://deploywithox.com/docs/operate/variables). ## Postgres, updates and backups Quickwit gets its own database and user on the server's Postgres, which you can browse in the Services tab or with `ox explore quickwit postgres`. It holds only the metastore. The index files sit under `qwdata`. To move to a newer release, merge its commit into your fork and push, or run `ox deploy quickwit --wait`. Quickwit's [upgrade page](https://quickwit.io/docs/get-started/upgrade) says the move to 0.9 ran SQL migrations on the metastore at first start and that going back needs a metastore backup. A newer release and a rollback were not tested. The run's backup came from Back up now on the Backups tab: a Postgres dump of the metastore and a `tar.gz` of the kept `qwdata` folder. ox backs up both each day too. Run `ox backups quickwit` to list them. A restore was not tested. The [backups page](https://deploywithox.com/docs/operate/backups) covers copies in an S3 bucket, and [self-hosting with ox](https://deploywithox.com/self-hosting) lists more apps. ## Frequently asked questions ### Do I need Docker to self-host Quickwit? No. Quickwit publishes a Docker image and release tarballs, but it compiles to a single binary. ox builds that binary on your server from your fork and runs it as a system service beside Postgres. An update is a push or one deploy command. ### Does Quickwit have a login or an admin account? No. Quickwit has no accounts, passwords or API keys, so there is no first user to create. The test agent made an index, added a document and searched for it with plain requests. Anyone who has the project's address can use the API, and the run put nothing in front of it. ### Does Quickwit need Postgres? Quickwit's own default metastore is a folder of files. This setup uses Postgres instead: ox sets up the database, and Quickwit creates its tables the first time it starts. Postgres holds only the metastore. The index files sit in the kept qwdata folder, and the run's backup covered both. ### Why does my search find nothing right after I add a document? Quickwit makes a document searchable only after it commits the split, which by default happens up to 60 seconds after the split starts (commit_timeout_secs). Add commit=force to the ingest request and it commits and waits before it answers. commit=wait_for waits for the normal commit. The test agent used commit=force. ### How much memory does self-hosted Quickwit use? The facts above give the memory in use on the run's server after its reboot. That figure covers the whole machine: Quickwit, Postgres, Caddy and the ox agent. The build also compiles Rust on the server. ox works on any server from 1 GB up and tells you when memory is why an app stopped. New to running apps on your own server? [How ox self-hosts your apps](https://deploywithox.com/self-hosting) shows what ox sets up on your server. On this page - [What you need](https://deploywithox.com/blog/self-host-quickwit#what-you-need) - [The steps to install Quickwit on Ubuntu](https://deploywithox.com/blog/self-host-quickwit#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-quickwit#config) - [Postgres, updates and backups](https://deploywithox.com/blog/self-host-quickwit#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-quickwit#faq) - [Do I need Docker to self-host Quickwit?](https://deploywithox.com/blog/self-host-quickwit#faq-docker) - [Does Quickwit have a login or an admin account?](https://deploywithox.com/blog/self-host-quickwit#faq-login) - [Does Quickwit need Postgres?](https://deploywithox.com/blog/self-host-quickwit#faq-postgres) - [Why does my search find nothing right after I add a document?](https://deploywithox.com/blog/self-host-quickwit#faq-search) - [How much memory does self-hosted Quickwit use?](https://deploywithox.com/blog/self-host-quickwit#faq-memory) Written by Saurav Sharma Builds ox. Writes about running apps on servers you own, without Docker and without a platform bill. [Older post How to self-host Redmine without Docker on your own VPS](https://deploywithox.com/blog/self-host-redmine) [Newer post How to self-host pretix ticketing on your own Ubuntu VPS](https://deploywithox.com/blog/self-host-pretix) ## Keep reading - Guides [Self-Hosted Open-Source Apps Deployed with ox: All 85](https://deploywithox.com/blog/self-hosted-open-source-apps-deployed-with-ox) ox deployed 85 open-source apps from pinned commits on fresh servers, with no Docker. The stacks, services, deploy times and a table of every app. Saurav Sharma Oct 17, 2026 16 min read - Guides [How to self-host AFFiNE on your own VPS without Docker](https://deploywithox.com/blog/self-host-affine) Run AFFiNE v0.27.4 on your own Ubuntu server with ox: Postgres with pgvector, Redis, a Rust and Node build, and an admin made from two variables. Saurav Sharma Oct 17, 2026 12 min read - Guides [How to self-host Akaunting on your own VPS without Docker](https://deploywithox.com/blog/self-host-akaunting) Run Akaunting 3.2.4 on your own Ubuntu server with ox: PHP, MariaDB, a scheduler and the first company and admin made on deploy, from the config that ran. Saurav Sharma Oct 17, 2026 10 min read ## Deploy to a server you own ox sets up systemd, Caddy and PostgreSQL on your Ubuntu server and deploys on every push. Free for your first project. [Sign up with GitHub](https://deploywithox.com/login/github) [Read the docs](https://deploywithox.com/docs)