Skip to main content

Running Your Own Software on a Device

This guide covers running a custom web application on a device — code that is not available as an obacht template. The application is started manually via Docker Compose or a shell script, kept running in the background, and exposed through the obacht Hosting tab.

Before you start

This guide assumes the repository has already been cloned to the device. If not, follow Advanced: Clone GitHub first.


How it works

An application running on the device listens on a port — a numbered address other programs use to reach it over the network. Common defaults are 3000, 8080, and 5000. The project README or start command output will indicate which port is used.

obacht can route a public domain to that port. The steps are:

  1. The application runs on the device and listens on a port (e.g. 3000)
  2. In the Hosting tab, a domain is bound to Local port 3000
  3. Visitors to the domain reach the application

The sections below cover two approaches: Docker Compose (if the project includes a docker-compose.yml) and shell scripts or direct commands (if the project is started with a single command). Both use tmux to keep the process running after the terminal is closed.


Option A: Docker Compose

Use this approach if the project includes a docker-compose.yml file.

1. Install Docker

Docker is not installed on Raspberry Pi OS by default. Run the following command in the terminal:

curl -fsSL https://get.docker.com | sh

This downloads and runs the official Docker install script. Installation takes a few minutes. When it completes, add the obacht user to the Docker group:

sudo usermod -aG docker $USER
warning

Disconnect and reconnect the terminal session for the group change to take effect.

2. Navigate to the project

cd my-project
ls

Confirm that docker-compose.yml is present.

3. Start the application

docker compose up -d

The -d flag stands for detached. Docker starts the containers defined in docker-compose.yml and returns to the prompt immediately. The application continues running in the background after the terminal is closed.

To verify the containers are running:

docker compose ps

To follow the log output:

docker compose logs -f

Press Ctrl + C to stop following the logs. The containers keep running.

4. Restart automatically on reboot

To restart the application when the device reboots, add restart: unless-stopped to each service in docker-compose.yml:

services:
app:
image: my-app
restart: unless-stopped
ports:
- "3000:3000"

Open the file with nano docker-compose.yml, add the line, save with Ctrl + O, exit with Ctrl + X, then apply:

docker compose up -d

5. Find the exposed port

Check the ports: section of docker-compose.yml. The format is host-port:container-port. The left number is the port on the device — this is the value to enter in the Hosting tab.


Installing Dependencies

Most projects require dependencies to be installed before the application can start. The steps differ depending on the language. Complete this section before starting the application in Option B below.

Node.js projects

Node.js is not installed on Raspberry Pi OS by default. Install it via the NodeSource repository:

curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt install nodejs -y

This installs both node and npm. Verify the installation:

node -v
npm -v

Then install the project's dependencies from within the project folder:

npm install

This reads package.json and downloads all required packages into a node_modules folder. The application can then be started with npm start or whichever command the README specifies.

Python projects

Python 3 is pre-installed on Raspberry Pi OS. The recommended approach is to install dependencies into a virtual environment — an isolated folder containing only the packages this project needs, separate from the rest of the system.

Create a virtual environment in the project folder:

python3 -m venv .venv

Activate it:

source .venv/bin/activate

The prompt changes to show (.venv) at the beginning, indicating the environment is active. Install the project's dependencies:

pip install -r requirements.txt
note

The virtual environment must be activated each time before starting the application. If the terminal session is closed and reopened, run source .venv/bin/activate again before running the app.

When using systemd for autostart (see below), the ExecStart line must point directly to the Python interpreter inside .venv — no activation step is needed in that case:

ExecStart=/home/obacht/my-project/.venv/bin/python app.py

Other runtimes

For projects in other languages or with other dependency managers, the project README is the authoritative reference. Common patterns follow the same structure: install a runtime, then install packages. If a Makefile is present, make install or make setup is often the intended first step.


Option B: Shell Scripts and Direct Commands

Use this approach if the project does not use Docker and is started with a single command such as node server.js or python app.py. Install all dependencies (see above) before proceeding.

What is tmux?

tmux is a terminal multiplexer. It runs processes in named sessions that persist after the terminal window is closed. The session can be re-attached later to inspect output or stop the process.

1. Install tmux

sudo apt update && sudo apt install tmux -y

2. Navigate to the project

cd my-project
ls -la

Identify the start command. Look for a start.sh, a package.json with a start script, a Makefile, or instructions in README.md.

3. Make the start script executable (if needed)

If the project includes a start.sh:

chmod +x start.sh

See Advanced: Unix Basics — Making a File Executable for details.

4. Start a tmux session

tmux new -s app

The prompt changes — the terminal is now inside a tmux session. A status bar appears at the bottom showing the session name.

5. Start the application

Run the project's start command, for example:

./start.sh

or

node server.js

or

python app.py

The application's startup output appears in the terminal.

6. Detach from the session

Press Ctrl + B, then D. The normal shell prompt returns. The application continues running inside the tmux session.

7. Re-attach to the session

To inspect or stop the application later:

tmux attach -t app

To list all running sessions:

tmux ls

8. Restart automatically on reboot

info

tmux sessions do not survive a device reboot. Use systemd to start the application automatically on boot.

Create a systemd service:

sudo nano /etc/systemd/system/myapp.service

Paste the following, replacing the paths and command to match the project:

[Unit]
Description=My App
After=network.target

[Service]
User=obacht
WorkingDirectory=/home/obacht/my-project
ExecStart=/home/obacht/my-project/start.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target

Save with Ctrl + O, exit with Ctrl + X, then enable and start the service:

sudo systemctl enable myapp
sudo systemctl start myapp

To check the status:

sudo systemctl status myapp

Exposing the Application via a Domain

Once the application is running it is listening on a port on the device. The next step is routing a domain to that port through obacht.

1. Identify the port

The port is shown in the start command output, the project README, or the ports: section of docker-compose.yml. A line such as the following indicates port 3000:

Server listening on http://localhost:3000

2. Open the Hosting tab

In obacht, open the device and go to the Hosting tab. If no domain has been added yet, click + Add domain and follow the wizard (see Templates & Domains — Adding a Domain).

3. Bind to a Local Port

Once the domain is verified, the domain row shows a Local port bind control. Enter the port number and click Bind.

obacht routes incoming traffic for that domain to the specified port on the device.


Quick Reference

TaskCommand
Start containers in backgrounddocker compose up -d
Check container statusdocker compose ps
Follow container logsdocker compose logs -f
Stop containersdocker compose down
Start a new tmux sessiontmux new -s app
Detach from tmuxCtrl + B, then D
Re-attach to tmux sessiontmux attach -t app
List tmux sessionstmux ls
Enable app to start on bootsudo systemctl enable myapp
Check systemd service statussudo systemctl status myapp