# Build and connect backend services

Choose a Docker Hub image, a Dockerfile, or native Node.js/Python source, then connect the service to your frontend.

Source: https://docs.rumata.dev/guides/backends
Reviewed: 2026-11-02

## Before you start

- A factory with permission to create and configure services.
- For source builds, a connected repository containing the committed backend files.

<a id="source"></a>

## Choose a service source

Open **System Explorer → Services → New service**. The Source control offers three ways to supply the program that Rumata will run.

| Source | Choose it when | What you supply |
| --- | --- | --- |
| Docker image | An existing container already provides the API, tool, or worker you need. | A container image reference and the settings required by that image. |
| Native runtime | Your backend is a Node.js or Python application and you want to configure its build and start commands directly. | Repository paths, runtime/version, build command, and start command. |
| Dockerfile | You need to control the container build, such as installing system packages or using a custom base image. | A committed Dockerfile and its build context in the repository. |

Source and service type are separate choices. A **Web service** accepts HTTP requests; a **Background worker** runs work without a web endpoint. Choose the runtime policy, resources, and storage for the workload, whichever source you use.

<a id="docker-hub"></a>

## Choose a Docker Hub image

1. Select **Docker image**, then **Choose an image**.
2. Search public Docker Hub images by name or namespace. The picker also offers quick setups such as Gotenberg, NGINX, and HTTPBin.
3. Select the intended image and version tag. Review the publisher’s documentation for its HTTP port, environment variables, startup requirements, and writable directories.
4. Check **Container image** and the service settings after selection. You can also enter an image reference directly. Use the optional private-registry configuration when the image requires registry authentication.
5. Choose the service name, service type, runtime policy, and endpoint access. Save settings, then deploy when ready.

An image reference identifies a repository and optionally a tag, for example `namespace/image:version`. A tag is a named version that its publisher can update; a digest identifies particular image content. Prefer an explicit reviewed version over relying on a changing `latest` tag.

> **Check your result**
> The service uses the intended image and port, starts successfully, and responds to a harmless health check if it is a web service. An image starting successfully does not prove that its application authentication is configured.

<a id="native"></a>

## Build native Node.js or Python source

1. Select **Native runtime**. Review **Backend folder**, **Build context**, and the optional **Git branch or ref**. Paths are relative to the repository root.
2. Choose **Node.js** or **Python** under Native runtime, then enter an exact supported Runtime version, including its patch number.
3. Set the Build command for dependency installation and any compilation your application needs. Leave it empty only when no build is needed.
4. Set the Start command to launch the application. For a web service, listen on `0.0.0.0` and the supplied `PORT`.
5. Review environment variables, service type, HTTP port, resources, and endpoint access. Commit and push the source before requesting a production build.
6. Save settings and deploy. Read the build logs and test the running service.

For Node.js, the form offers `npm ci && npm run build --if-present` and `npm start`. These commands require a compatible package file, lockfile, and start script. For Python, use installation and startup commands appropriate to your project and its dependency files; switching runtimes does not convert your application.

> **Build versus runtime**
> The form states that environment variables are available at runtime, not during builds. Do not make a build depend on a runtime secret. A production build uses committed source; private development uses the working files on the development machine.

<a id="dockerfile"></a>

## Build from a Dockerfile

1. Select **Dockerfile**.
2. Review **Backend folder**, **Build context**, **Git branch or ref**, and **Dockerfile path**. Use paths relative to the repository root.
3. Make sure files copied by the Dockerfile are inside its build context and are not excluded by the applicable `.dockerignore`.
4. Keep dependency installation and compilation in build instructions, and configure the container’s startup command for the running application.
5. Commit and push the Dockerfile and its source files. Save the intended settings, deploy, and inspect the build logs.

A Dockerfile is a recipe for building an image. A Docker image source instead runs an already-built image. Native runtime builds expose language and command settings directly; Dockerfile builds put the container setup under your control.

> **Web service readiness**
> The application inside the container must listen on the configured HTTP port and an interface reachable outside its own process, such as `0.0.0.0`. Declaring `EXPOSE` in a Dockerfile does not start an HTTP server.

<a id="frontend-bindings"></a>

## Connect the frontend with rumata.backends.json

The frontend’s `rumata.backends.json` records backend bindings. It sits in the frontend directory, for example `factories/<factory-id>/frontend/rumata.backends.json`. It connects a frontend configuration name with a service ID and the intended production and development endpoints and access modes.

1. Open Code and find `rumata.backends.json` in the frontend that should use the service.
2. Check that the binding points to the intended service. Keep development and production endpoints separate; do not replace the production endpoint with a private preview URL.
3. Make sure the frontend’s API client uses the corresponding configuration name and the authentication required by the selected endpoint access mode.
4. Commit the binding with the frontend changes. Review the frontend deployment’s backend information and deploy the connected frontend and service together when Rumata requires a coordinated deployment.
5. Test the API call in private preview and on the intended deployed environment, including an unauthorized request when the API should be private.

> **Bindings are configuration**
> A binding is not a secret or an access grant. It does not publish a service or authorize a caller by itself. Keep credentials out of this file and out of browser-exposed frontend variables.

## Further reading

- [Dockerfile overview](https://docs.docker.com/build/concepts/dockerfile/)
- [Docker image references and digests](https://docs.docker.com/reference/cli/docker/image/pull/)

## Related guides

- [Services](https://docs.rumata.dev/guides/system-explorer-services)
- [Publish your app](https://docs.rumata.dev/guides/publishing)
- [Call workflows with API keys](https://docs.rumata.dev/guides/api-keys)
- [Keys & secrets](https://docs.rumata.dev/guides/system-explorer-secrets)