Skip to main content

App Hosting

An app is a program of yours that we run from a GitHub repository and keep running: a web dashboard, an API, a webhook receiver, a status page, a queue worker, a Discord bot. You point us at the repository, we install it, build it if it needs building, and start it. Every push to your branch deploys the new version.

  • Languages: Node.js and Python, detected from your repository (the full list is below).
  • Free tier: your first app is free, 256 MB of RAM, always on, no card needed.
  • Paid tiers: $2/mo or $20/yr and up per app, for more memory and more than one app.
  • Regions: Europe West (France), Canada East (Montreal) and USA West (Oregon).

Apps live under Apps in your control panel. A Discord bot is an app with a token, so everything on this page applies to bots too. The bot-specific parts (tokens, intents, the premade bots) are on the Discord Bot Hosting page.

Create an app from a repository

  1. Push your code to a GitHub repository, public or private.
  2. In the panel, go to Apps → Host an app.
  3. Fill in:
    • Name a label for the app, only you see it.
    • Region pick the one closest to you and your players.
    • Kind choose App. (Choose Discord bot if it logs in to Discord with a token, which adds the token field.)
    • GitHub repository for example https://github.com/you/my-app. Add a Branch if it is not your default one.
    • Start command and Build command, both optional. Leave them blank and we work them out from your repository.
    • Language, which is on auto-detect unless you set it.
    • Environment variables, one KEY=value per line. Keys and tokens belong here, never in the repository.
  4. Click Deploy. We clone the code, install the dependencies and start the app.

Your first app is free once your email is verified. For more apps, or more memory, add App Hosting to your subscription in the plan builder.

Runtimes

We read your repository and pick the runtime. You can override it under Language, and set your own Start command, at any time.

Your repository containsRuntimeInstalled withStarted with
package.jsonNode.jsnpm, pnpm, yarn or bun, whichever your lockfile or packageManager pin namesnpm start, or your entry file if there is no start script
requirements.txt, pyproject.toml or PipfilePythonpip, in a virtual environment we keep for youpython bot.py or python main.py
bun.lock, bun.lockb or a packageManager pin naming bunBunbun installyour start script with bun, or the entry file
deno.json or deno.jsoncDenomodules cached under /datadeno task start, or deno run -A on the entry file
go.modGogo build of your main package, modules and builds cached under /datathe built binary
pom.xml, build.gradle or build.gradle.kts, or a .jar at the rootJava 21mvn package or gradlew build (tests skipped)java -jar on the built or committed jar
composer.json or index.phpPHPcomposer install without dev packagesPHP's built-in server on PORT, serving public/ when it exists, else the root
GemfileRuby 3.4bundle install into /datayour start command, or rackup when there is a config.ru
index.html, or a build script producing dist, build, public, out or _siteStatic siteyour build script when there is onea small static server on PORT (set SPA=1 for single-page apps)

Set a Start command when your entry point is somewhere else, for example node dist/server.js or python -m myapp.

Listening on a port

Every app gets a PORT environment variable, whether or not it has a web address. The default is 8080.

Your web server has to listen on that port and on 0.0.0.0. A server bound to 127.0.0.1 only answers itself, so nothing outside the container, including your web address, can reach it.

// Node.js (Express)
app.listen(process.env.PORT || 8080, "0.0.0.0")
# Python (FastAPI with uvicorn)
uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))

An app with no web server, a Discord bot or a worker, can ignore PORT entirely.

Environment variables

Tokens, API keys, database URLs and any other configuration live in environment variables, not in your repository. They are injected into the app at runtime.

  • On create: fill in the Environment variables box, one KEY=value per line.
  • Later: open the app → Environment. The variables are a table, values masked. Add rows, remove rows, then Save once and the app restarts with the new values.
  • Names must start with a letter or an underscore, for example DISCORD_TOKEN or DATABASE_URL.

Some variables we set for you: PORT always, APP_URL while a web address is enabled, and the database credentials when you create a database.

Build step

Every deploy runs three things in order: the install, the build command, then the start command.

If your app has to be compiled before it runs (TypeScript, esbuild, tsup, a bundled dist/ folder), you do not have to commit the compiled files. Leave the build command blank and we detect the build:

  • When the file your start command runs is not in the repository (say node dist/index.js with dist in .gitignore) and your package.json has a build script, we install your devDependencies and run that script before starting the app.
  • In a workspace (pnpm, npm or Yarn workspaces), we build only the package the app starts and the workspace packages it depends on, so a sibling web app in the same repository never has to build.
  • A committed entry file is never built over. An app whose index.js is in git starts as before, even if the repository has a build script.

To build differently, set a Build command on the app's page. It runs on every deploy, exactly as written:

pnpm --filter @workspace/api run build

A failed build prints its error in the live console, and every restart repeats one line naming the file the build never produced. Fix it in your repository, or fix the build command, then press Redeploy.

Web address

A paid app can answer at https://<name>.fadehost.app with HTTPS, for $2/mo or $20/yr per app. Use it for a dashboard, OAuth2 redirect URLs, incoming webhooks or a status page. Open the app → Web address, pick a name, and it is live within seconds.

The full section, including what your app has to do and what is not allowed, is under Web address and applies to every app, bot or not.

A few rules about the name itself:

  • 3 to 32 characters, lowercase letters, numbers and dashes.
  • One rename a day, with ten minutes after a change to fix a typo for free.
  • Switching the address off takes it down at once and holds the name for a day.

Storage: what survives a deploy

Your code is checked out at /data/app, which is also the app's working directory. Every deploy resets it to match your repository, so a file your app wrote next to its code can be gone after the next push.

Anything under /data is a volume that survives deploys and restarts. Write runtime data there, with an absolute path:

const file = "/data/storage/state.json"

For anything more than a file or two, use a database. Every paid app includes a one-click MySQL database (open the app → DatabaseCreate database) and the credentials are injected into the environment. PostgreSQL and Redis are available as managed databases on the same private network.

Plans and limits

FreeStarterStandardPro
Price / app / month$0$2$3$6
Price / app / yearfree$20$30$60
RAM256 MB1 GB2 GB4 GB
vCPU0.25113
Always on, auto-deploy
Live console, crash doctor
1-click MySQL database
Web address (https://name.fadehost.app)+$2/mo+$2/mo+$2/mo
Apps per account1 (verified email)MultipleMultipleMultiple

Every app runs in a hardened container: non-root, a read-only filesystem apart from its own storage, and hard memory and CPU limits. It restarts on its own if it falls over, with no sleep timer and nothing to renew.

Example apps

Ready-made apps you can deploy from the panel (Apps, Host an app, One-click template) by filling in a field or two. Each is a public FadeHost repository you can read, fork and change.

AppWhat it doesRuntime
Server status pageA public page of your servers: online or sleeping, who is on, the address to join.Node.js
Whitelist applicationsA form players fill in, an admin page for staff, the whitelist command run on approval, an optional Discord notice.Node.js
Bot with a dashboardA welcome and log bot whose settings live on a web page behind Discord login.Node.js
Activity digestWho played and for how long, summed up once a day to a Discord webhook, with today's page.Python
Server guide siteRules, how to join and the mod list as a static site edited in Markdown.Static site
Express API starter, Flask API starterBare services wired to the port and the persistent folder, ready to build on.Node.js, Python

The status page, the whitelist app and the digest talk to the FadeHost API for you: the panel creates their access token when you deploy them, so there is nothing to paste. Each README lists the environment variables.

What is not allowed

App hosting runs web apps and workers. It is not for:

  • phishing or credential-harvesting pages,
  • proxies and tunnels of any kind, which get the app stopped,
  • adult or illegal content,
  • bulk file or media delivery through the web address,
  • raw TCP or UDP services, outbound mail, or workloads that need privileged containers or a GPU,
  • traffic far beyond fair use.

The full rules are in the terms of service. Report an abusive app to support@fadehost.com.

Troubleshooting

The address says the app is not listening

The web address is on, but visitors get a page saying the app is not answering on port N, and the Web address card says the same.

  1. Check the app is actually running. The live console shows whether it started.
  2. Check it listens on 0.0.0.0, not 127.0.0.1 or localhost.
  3. Check the port. Read PORT from the environment, or set the card's port field to the one your app hard-codes. The change takes effect at once, no restart needed.
  4. Some frameworks need telling: next start -H 0.0.0.0 -p $PORT, flask run --host=0.0.0.0 --port=$PORT.

The app restarts over and over

Open the app and read the crash doctor card. It reads the logs and names the cause, usually within a minute. The usual reasons:

  • a missing environment variable, so the app throws on start,
  • a dependency that is installed on your machine but missing from package.json or requirements.txt,
  • a build that never produced the file the start command runs (the console names that file on every restart),
  • a script that finishes instead of staying up. An app that exits cleanly looks like a crash to us, because nothing is left running.

Fix it in your repository or the environment, then press Redeploy. The live console keeps everything the app printed, so you can see what it said last.

Need help?

Join our Discord and we will get your app running.