How a Renode app server runs
Where your code lives, which port it must listen on, the order a server boots in, how GitHub deploys work, where .env goes and when a server restarts. The rules every RE:NODE app server follows.
All docs pages
These pages describe how an application server on RE:NODE actually runs, so that you - or an AI assistant working for you - can deploy to one without guessing. They cover the app hosting lines (Node.js, Python, Go, Java, Rust, C#/.NET, Bun, Deno and Laravel / PHP), web hosting and database hosting. Every server is managed from the panel at panel.renode.space.
If you only read one section, read The five rules below. Nearly every failed first deploy breaks one of them.
The five rules#
- Listen on `0.0.0.0` and on the port in `SERVER_PORT`. Exactly one port is reachable from outside: the one your server was given. Never hardcode a port and never bind
localhostor127.0.0.1. - Give the server something to start. On Node.js that is a
startscript inpackage.json. On Python it is the entry file named on the Startup tab. A web hosting server starts nothing - it serves files. - Build before you serve. There is no separate build server. Either the start script builds, or the built output is committed.
- Keep secrets out of the repository. Upload
.envthrough the Files tab, or set variables on the Startup tab. - Stay inside the memory limit. It is a hard ceiling. A process that reaches it is killed with no error message - the console simply stops.
The container#
Each server is one container. Your process runs as an unprivileged user, so there is no root, sudo, apt, systemd or Docker inside it. Install what you need through your language's own package manager (npm, pip), which works without root.
Your code lives in /home/container, and only /home/container persists. Anything your app writes at run time - uploads, a SQLite file, logs you want to keep - belongs under that folder. You can browse and edit it in the panel's Files tab or over SFTP.
The port#
The panel gives every server an allocation: an address and a port, shown on the server's Network tab. That port is the only one reachable from outside, and it reaches your process through these environment variables:
| Variable | Value | Set when |
|---|---|---|
SERVER_PORT | The server's port | Always |
PORT | The same port, unless your project sets PORT itself | The panel starts a linked repository |
HOST, HOSTNAME | 0.0.0.0 | The panel starts a linked repository |
Read SERVER_PORT (or PORT) in your code. A port written into the code is reachable from inside the container and from nowhere else, unless it happens to match by coincidence. If your program needs a second port, add another allocation on the Network tab - a port that is not allocated is not reachable.
A web hosting server is the exception: its image already runs a web server bound to the port, so you do not bind anything.
Deploying from GitHub#
Application servers deploy from GitHub through the panel's GitHub App, so private repositories work and no token is ever pasted into your code. On the server's GitHub tab you install the app, pick a repository and a branch, and choose two switches:
- Pull the latest commit every time the server starts - fetch the branch every time the server starts. With it off, the branch is fetched on the first start only and later starts use the files already there.
- Restart the server when someone pushes to this branch - when somebody pushes to the branch, the server restarts within seconds and comes back on the new commit. A stopped server is started, so the push goes live either way. Turning this on also fetches on every start.
The fetch writes the branch into the code folder (/home/container unless the GitHub tab says otherwise), over what is already there under the same names. Files elsewhere in the container are left alone. Where the image has git, the fetch is a shallow git fetch and reset --hard; on images without git, the branch is downloaded and unpacked over the folder, which means a file you deleted from the branch stays on the server until you remove it.
How a server boots#
With a repository linked, a Node.js-capable server goes through these steps every time it starts:
- The branch is fetched into the code folder (every start, or only the first - see above).
- If the server type defines a setup command, it runs after the fetch.
- The environment gets
PORT(fromSERVER_PORT, unless your project sets it),HOST=0.0.0.0andHOSTNAME=0.0.0.0. - If
package.jsondefines astartscript:npm install, thennpm run start(Bun's own installer and runner on Bun images). The server type's own startup command is not run. - Otherwise, on Node.js, the first file that exists among
index.js,server.js,app.js,main.js,bot.js,index.mjs,index.cjs, the same names undersrc/, and then their.tsversions, is started withnode- or withts-nodefor a.tsfile. - If none of that applies, the server type's own startup command runs.
Other server types boot their own way. A Python server runs the entry file named on the Startup tab after installing requirements.txt - see Python. A web hosting server runs nothing from your repository - see Static sites and web hosting. A database server starts its engine - see Databases.
Secrets and .env#
A .env file is not in your repository, and the fetch does not create one. Upload yours through the Files tab into the code folder, and keep a copy somewhere other than the server. Alternatively, set values as variables on the Startup tab.
In the repository, add .env to .gitignore and commit a .env.example that lists every variable with no values. Read configuration from the environment and fail with a clear message when a required value is missing - it turns a confusing crash into a one-line fix.
When changes go live#
| Your setting | After a push |
|---|---|
| Restart on push on | The server restarts by itself within seconds, on the new commit |
| Pull on every start on, restart on push off | Restart the server when you want the new commit |
| Both off | Later starts keep the files from the first fetch |
| Web hosting | The panel writes the files on push (with restart on push on) and when you save the GitHub tab. A restart fetches nothing |
Memory and crashes#
Each plan has a memory limit, and it is a hard ceiling. When a process reaches it, the kernel stops the container and it restarts clean - there is no stack trace and no final line, the console just stops. Build steps are the usual cause on small plans: a Next.js or TypeScript build can need more memory than the app itself. If the build is what gets killed, build locally and commit the output, or move to a larger plan.
The panel watches for crash loops. A server that restarts by itself three times in an hour gets a warning on its page and a support ticket; at six it is suspended. Restarts you asked for are not counted.
Check before you deploy#
Once a repository is linked, the panel can run a pre-flight check: it reads the repository and reports what will break - a missing start script, a hardcoded port, a build that never runs, a Node version mismatch, a project that expects a .env. There is no AI involved; it is the panel reading your files against the way this server boots.
Where next#
- Node.js - start scripts, frameworks, TypeScript and Node versions.
- Python - entry files,
requirements.txtand production servers. - Static sites and web hosting - serving files as they are.
- Discord and Telegram bots - tokens, restarts and state.
- Databases - connecting an app, and where passwords live.
- Custom domains - the proxy slot, DNS and certificates.
- Troubleshooting - when a server will not start or cannot be reached.
- Using AI assistants - the Connect AI link, connecting your account over MCP, and what an assistant may do.
Questions this does not answer? Open a ticket from the panel, or start from the overview. These pages are also available as plain text for AI assistants at /llms.txt.