[Blog](https://deploywithox.com/blog) [Guides](https://deploywithox.com/blog#c-guides) # How to self-host Logto on your own VPS without Docker Run Logto v1.44.0 on your own Ubuntu server with ox: a pnpm build, a Postgres of its own and the Admin Console on its own address. The config that ran. Saurav Sharma Oct 17, 2026 9 min read On this page - [What you need](https://deploywithox.com/blog/self-host-logto#what-you-need) - [The steps](https://deploywithox.com/blog/self-host-logto#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-logto#config) - [Postgres, and no Redis](https://deploywithox.com/blog/self-host-logto#services) - [The sign-in address](https://deploywithox.com/blog/self-host-logto#address) - [Updates and backups](https://deploywithox.com/blog/self-host-logto#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-logto#faq) To self-host Logto you need an Ubuntu server, a fork of the Logto repo with one `ox.toml` file added, and five variables. In our run the first deploy took about 7 minutes, and ox set up a Postgres of its own for it. **How we tested** On Oct 17, 2026, ox deployed Logto v1.44.0 from commit [`79e9e3b0`](https://github.com/logto-io/logto/commit/79e9e3b0d9f505260d09c80d8a015e56fbc0ec01) 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, signed in, created an application in the Admin Console and saw it listed after a reload, and checked the app's services and its backup. [Logto](https://github.com/logto-io/logto) is an open-source sign-in service. Your apps send their users to Logto to register and sign in, and Logto hands back a token that says who the user is. It supports OpenID Connect, OAuth 2.1 and SAML, and has multi-tenancy, enterprise single sign-on, role-based access control and SDKs for more than 30 frameworks. In the Admin Console, a web app, you register your apps, choose how people sign in and see your users. Logto is a Node.js monorepo that keeps its data in Postgres, under the Mozilla Public License 2.0. ox deployed Logto v1.44.0 (commit 79e9e3b0) on Oct 17, 2026 on a fresh DigitalOcean server with 8 vCPUs and 16 GB of memory; the first deploy took 7 minutes and a redeploy took 7 minutes. - **First deploy:** 7 minutes, from adding the project until the app passed the run's first checks. - **Redeploy of the same commit:** 7 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:** 1266 MB of 15986 MB, for the whole server: Ubuntu, the app and its staging copy, 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/logto-io/logto](https://github.com/logto-io/logto) at v1.44.0, commit [`79e9e3b0`](https://github.com/logto-io/logto/commit/79e9e3b0d9f505260d09c80d8a015e56fbc0ec01). The Logto Admin Console Get started page after creating the admin account The Logto Applications list with the new application Verify Web App ## What you need - An Ubuntu LTS server. The facts above give the size the run used. Logto and a staging copy of it shared that server. - A GitHub account to fork `logto-io/logto`. You open your ox account by signing in with it. - A username and a password for the first administrator. Logto's email, SMS and social connectors each need an account elsewhere. The run set up none, so passwordless sign-in and "Forgot password" stayed off, and no connector was tested. ## The steps Press Add a server in the ox dashboard and run the install command it shows, as root, on your VPS. It adds the ox agent and Caddy and nothing else. Fork `logto-io/logto` and check out the tag `v1.44.0`, the release the run deployed. Add the `ox.toml` shown below to the root of the fork, then commit and push. Logto needs no other added file. Next write `logto.env` with one `KEY=value` line for each of the five keys in the variables list. With the [ox CLI](https://deploywithox.com/docs/cli) signed in, run: Shell ```bash ox new /logto ox review logto --from-file logto.env --wait ``` ox names the project after the repo, so it is `logto` here. The review saves your values and starts the first deploy, and `--wait` prints the run until it ends. The [quickstart](https://deploywithox.com/docs/quickstart) shows the same steps in the console. When the deploy is green, open the Admin Console. Its address is the project's address with `admin.` in front of the host name. The first visit shows Welcome to Admin Console. Press Create account and pick a username and a password. Logto wants at least 8 characters and refuses a password found in a public leak. That first account is the administrator, and the console takes no sign-up after it. Create it right after the deploy, because until it exists anyone who reaches that address can. Logto then asks once for an email address, and the run gave it an example.com one. The test agent tried a wrong password, which Logto refused, then signed in and opened Applications. It pressed Create application, chose the Next.js (App Router) card, named the app and created it. After a reload, Applications still listed it, as a Traditional Web app with its App ID. Logto ran on ox's preview address only, so a domain of your own was not part of the run. The [domains page](https://deploywithox.com/docs/operate/domains) says how ox adds one. ## The ox.toml, line by line TOML ```toml # Logto: an OIDC identity provider, a pnpm monorepo. The steps are its # Dockerfile's: build every package, link the built-in connectors into # packages/core/connectors, then seed the database and deploy its # alterations before the start. The Admin Console has an address of its # own (M-3d) served by the app's own process: Logto picks the admin tenant # by the request's host (ADMIN_ENDPOINT), and ADMIN_DISABLE_LOCALHOST # closes its fixed second listener on 3002. [app] # The root's start is `cd packages/core && npm start`; running node itself # lets the stop signal reach Logto. start = "cd packages/core && NODE_ENV=production exec node ." health = "/api/status" [build] commands = ["pnpm -r build", "pnpm cli connector link -p ."] # pnpm passes a `--` on to the script, where yargs reads what follows as a # positional: the flag goes right after the command. --swe skips the seed # when the database already has it (a redeploy). Without a TTY the # alteration deploy needs its target named (`latest`). migrate = "pnpm cli db seed --swe && pnpm cli db alteration deploy latest" [services] # db seed runs CREATE ROLE (a role per tenant), which only a superuser may: # the shared postgres gives each project a plain login role, a private # instance makes the project's role its superuser. postgres = { only_for_this_project = true } [workers] # No run: the app's process serves the admin names, with the host kept. admin = { public = true } ``` The steps follow Logto's own Dockerfile. - `start` runs the core package with node itself. Logto's own start script goes through npm, so the config uses `exec` to make node the process ox stops. - `health` is `/api/status`, a Logto route that answers 204 with no body. ox switches to a new release only once it answers. - The build `commands` are two Dockerfile steps. `pnpm -r build` builds every package in the workspace. `pnpm cli connector link -p .` links the built-in connectors, the plug-ins for email, SMS and social sign-in, into the core package. There is no install line: Logto's `package.json` asks for Node 22.14 or later in the 22 line and pnpm 9 or 10, and ox reads that and `pnpm-lock.yaml`. - `migrate` runs two Logto commands. `db seed` creates the tables and the default and admin tenants. Its `--swe` flag skips the seed when Logto's configs table exists, so a redeploy does not seed again. The flag goes right after the command because pnpm passes a `--` on to the script, and the Docker Compose file's npm drops it. `db alteration deploy latest` applies Logto's pending database upgrades, and with no terminal it needs a target named. - `[services]` asks for Postgres with `only_for_this_project`. The seed creates a database role for each tenant, which only a superuser may do. A shared Postgres gives a project a plain login role. A private instance makes the project's role its superuser. - `[workers]` holds `admin` with `public = true` and no command. One Logto process serves the sign-in side and the Admin Console and tells them apart by the host of each request. The line gives the console its own address, and ox sends that address's requests to the app's process with the host kept. Nothing else runs. Logto keeps its tenants, applications, users and signing keys in Postgres, so the config has no `[storage]` folder. The test agent found no timers or queue workers, and the config has no cron jobs. Shell ```bash DB_URL ENDPOINT ADMIN_ENDPOINT ADMIN_DISABLE_LOCALHOST TRUST_PROXY_HEADER ``` `DB_URL` is `${DATABASE_URL}`, the address of the Postgres ox set up, and Logto will not start without it. `ENDPOINT` is `${PUBLIC_URL}`, the project's address and the one your apps send people to. `ADMIN_ENDPOINT` is `${ADMIN_PUBLIC_URL}`, the address ox gives the `admin` worker, and Logto picks its admin tenant when a request arrives with that host. See [variables](https://deploywithox.com/docs/operate/variables) for how references work. `ADMIN_DISABLE_LOCALHOST` and `TRUST_PROXY_HEADER` are on and off switches, and the run switched both on. Without the first, Logto also listens on a fixed second port, 3002, for the admin tenant. With it, only `ADMIN_ENDPOINT` answers for the console. The second makes Logto trust the forwarded headers its proxy sets, so it sees the address the visitor used. ## Postgres, and no Redis Postgres is the only service. The private instance is a unit of its own, and the staging copy the run deployed beside production has another. After the reboot the test agent found the four units active with no restarts: the app and Postgres, for production and for staging. They were still active about 20 seconds later. The journal warns "No Redis client initialized, skipping". Logto reads `REDIS_URL` for an optional cache and carries on without it. ## The sign-in address Opening the project's own address, not the admin one, redirects to `/unknown-session`, Logto's page for a visit with no sign-in under way. That is expected, since your apps use this address as their sign-in endpoint. To see a real sign-in page there, open `/demo-app`, Logto's Live Preview. ## Updates and backups To move to a newer release, merge its tag into your fork and push, or run `ox deploy logto --wait`. ox builds the new release beside the running one, runs `migrate`, and switches when `/api/status` answers. Before each migrate it dumps Postgres. The run's redeploy used the same commit, so a move to a newer Logto version was not tested. Backups need no setup. The run's backup folder held three Postgres dumps: the daily one, one from Back up now, and the one ox takes before a migrate. `ox backups logto` lists them, and the Backups tab shows the same list. Logto's signing keys live in Postgres, so each dump carries them. A restore was not tested. The [backups page](https://deploywithox.com/docs/operate/backups) covers S3 copies. ## Frequently asked questions ### Do I need Docker to self-host Logto? No. Logto's README offers Docker Compose, or Node.js with a PostgreSQL you provide. ox follows the Node.js route for you: it builds your fork on the server and runs Logto as a system service beside a Postgres of its own. No image is pulled, and an update is a push to your fork or one deploy command. ### How do I make the first Logto admin account? No variable makes it. Open the Admin Console address, press Create account and choose a username and password. Logto then closes sign-up on that console. Do it as soon as the deploy is green, because until the account exists the address is open to anyone. Adding more administrators was not tested. ### Which database does Logto need? Postgres, and nothing else. Redis is an optional cache that Logto skips when it is absent. ox starts a Postgres for the project alone, because Logto's seed creates a role per tenant, which needs a superuser. The run's backups held dumps of it. ### How much memory does self-hosted Logto use? The facts above give what the whole server used after the reboot. That figure counts production and the staging copy, two Postgres instances, Caddy and the ox agent. The monorepo's build also runs on the server. ox takes any server from 1 GB up, and says so 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-logto#what-you-need) - [The steps](https://deploywithox.com/blog/self-host-logto#steps) - [The ox.toml, line by line](https://deploywithox.com/blog/self-host-logto#config) - [Postgres, and no Redis](https://deploywithox.com/blog/self-host-logto#services) - [The sign-in address](https://deploywithox.com/blog/self-host-logto#address) - [Updates and backups](https://deploywithox.com/blog/self-host-logto#updates) - [Frequently asked questions](https://deploywithox.com/blog/self-host-logto#faq) - [Do I need Docker to self-host Logto?](https://deploywithox.com/blog/self-host-logto#faq-docker) - [How do I make the first Logto admin account?](https://deploywithox.com/blog/self-host-logto#faq-admin) - [Which database does Logto need?](https://deploywithox.com/blog/self-host-logto#faq-database) - [How much memory does self-hosted Logto use?](https://deploywithox.com/blog/self-host-logto#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 Mastodon without Docker on your own VPS](https://deploywithox.com/blog/self-host-mastodon) [Newer post How to self-host LobeHub (AI chat) on your own VPS](https://deploywithox.com/blog/self-host-lobehub) ## 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)