
Deploy Presenton v0.9.3 | AI Presentations + API, Decks Survive Redeploy
AI presentations + PPTX/PDF API. Decks persist, admin login pre-set.
presenton
Just deployed
/app_data
Deploy and Host Presenton on Railway
Presenton is a self-hosted AI presentation generator: describe a deck or upload a document, pick a template, and get editable slides plus PPTX and PDF export — with an HTTP API so your own app can generate decks too. It talks to whichever model you already pay for (OpenAI, Anthropic, Google, Bedrock, OpenRouter, Ollama and ~15 more), so there is no per-seat subscription and your prompts stay on your own deployment.
This template runs it as a single service with a persistent volume and an admin account that already belongs to you. Both of those matter more than they sound, and both were measured on a live Railway deploy before this template was published.
About Hosting
Everything Presenton keeps lives in one directory, and without a volume it is gone on every
redeploy. /app_data holds the SQLite database (your presentations, slides, templates,
image assets, webhook subscriptions), the uploaded documents, the generated exports, the
custom fonts and the saved provider settings. A Presenton service deployed without a volume
looks completely healthy — it answers every request, the dashboard loads, decks generate —
and then a redeploy, a platform restart or a variable change resets it to an empty install.
This template mounts a volume at /app_data. Verified on this exact configuration: a
redeploy came back with the database intact and the same login working.
Your instance is not open for someone else to claim. Presenton requires a login, but with
no credentials configured it boots unclaimed: GET /api/v1/auth/status returns
{"configured": false} and the first person to POST to /api/v1/auth/setup — from anywhere
on the internet, with no authentication — becomes the administrator, with
"role": "admin". That account can read every deck and open the provider settings page where
your model API keys are stored.
Reproduced on a stock deploy, then reproduced again after a restart:
GET /api/v1/auth/status -> {"configured": false}
POST /api/v1/auth/setup -> 200 {"username": "attacker", "role": "admin"}
[redeploy]
GET /api/v1/auth/status -> {"configured": false} # the account is gone with the DB
POST /api/v1/auth/login -> 428 # the real owner is locked out
POST /api/v1/auth/setup -> 200 {"username": "attacker2", "role": "admin"}
Without a volume the two problems compound: every redeploy hands the instance back to whoever reaches the URL first.
This template creates your administrator at first boot from AUTH_PASSWORD, a generated
secret unique to your deployment and visible in the Railway variables panel. Log in as
admin with that value. On the same live check:
GET /api/v1/auth/status -> {"configured": true}
POST /api/v1/auth/setup -> 409 {"detail": "Credentials already configured"}
POST /api/v1/auth/login -> 200 admin
GET /api/v1/ppt/... -> 401 (unauthenticated)
It is served over HTTPS. Presenton's bundled nginx has listen 80 compiled into the
image and does not read Railway's injected PORT, which is why it is often published behind
a raw TCP proxy — a http://…proxy.rlwy.net:PORT address with no certificate, for an app
whose login form and provider API keys travel over it. This template rewrites that listener
to the injected port before the app starts, so the deploy gets an ordinary
https://…up.railway.app domain.
The version is pinned to v0.9.3-beta rather than tracking latest, so an unrelated
restart cannot move your deployment onto a build you have not tried — this app migrates its
database on startup, and those migrations only go forward.
Cost. One always-on service. The image carries a headless Chromium (used to render PPTX and PDF exports) and a local embedding model, so give it a plan with room; there is no separate database, worker or cache to pay for.
Why Deploy Presenton on Railway?
Railway supplies the HTTPS domain, the persistent volume and the restart policy this app needs, with no reverse proxy to configure and no certificates to renew. The template arrives with the volume mounted, the port fixed, the admin account created and the version pinned — so the deploy is usable the moment it turns green, and still yours after the first redeploy.
Common Use Cases
- Decks from a prompt or an outline — describe the talk, choose a template, edit the slides that come back, export to PPTX or PDF.
- Presentations generated from documents — upload a PDF, DOCX or existing PPTX and turn it into a new deck; the image includes OCR for scanned files.
- A presentation API inside your own product —
POST /api/v1/ppt/presentation/generatereturns a deck, so an app, an internal tool or an agent can produce slides on demand. - Bring-your-own-model AI slides — point it at OpenAI, Anthropic, Google, Bedrock, OpenRouter, LM Studio or a self-hosted Ollama, and pay your provider directly instead of a per-seat SaaS.
Dependencies for Presenton Hosting
- Persistent volume —
/app_data: the SQLite database, uploads, exports, fonts and saved provider settings. This is the whole application state. - An LLM provider key — added in the app's settings page after you log in (or set as service variables); Presenton itself is free and open source.
- Optional image provider — Pexels, Pixabay or an image model, for slide artwork.
Deployment Dependencies
- Upstream project: Presenton, Apache-2.0,
image
ghcr.io/presenton/presenton, pinned tov0.9.3-beta. - No external database or cache: Presenton runs FastAPI, Next.js and nginx in one container
and stores its data in
/app_data.
Implementation Details
Variables you set: none. AUTH_PASSWORD is pre-filled with a generated secret — change it
before deploying if you like, but it does not need to be touched.
Applied at startup so the deploy form stays empty: AUTH_USERNAME=admin,
MIGRATE_DATABASE_ON_STARTUP=true, DISABLE_ANONYMOUS_TRACKING=true, and the nginx listener
rewritten from port 80 to Railway's injected PORT.
After deploying: open https://, log in as admin with the AUTH_PASSWORD
value from the variables panel, then add your model provider key on the settings page and
generate a deck. To change the admin password later, set a new AUTH_PASSWORD together with
AUTH_OVERRIDE_FROM_ENV=true; upstream requires that flag so an existing account and its
presentations are never silently replaced.
Template Content
