Skip to main content

Run your own software

Run a web application that is not an Obacht template on a Raspberry Pi or Linux PC. You start it yourself with Docker Compose or a shell command, keep it running in the background, and point a domain at the port it listens on. You need the repository already cloned to the device, see Clone from GitHub.

How it works​

An application 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 the start command's output tells you which port is used.

Obacht can route a public domain to that port:

  1. The application runs on the device and listens on a port (for example 3000).
  2. In the device's Hosting tab, a domain is bound to that port.
  3. Visitors to the domain reach the application.

Two approaches are covered below: 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). The second one uses tmux to keep the process running after the terminal is closed.

If your project is a Compose project and you want Obacht to manage it like an app, with its own web address and start/stop from the dashboard, look at Run your own Docker Compose instead.

Option A: Docker Compose​

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

Docker is already there​

The Obacht install command installs Docker if it is missing, and the obacht user is in the docker group. Check:

docker --version
docker compose version
cd my-project
ls

Confirm that docker-compose.yml is present.

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 keeps running 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.

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

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.

warning

Ports 80 and 443 are taken by Caddy, the web server the Obacht agent runs. Pick another host port for your project or it will not start.

Installing dependencies​

Most projects need dependencies installed before the application can start. The steps differ by language. Do this before starting the application in Option B.

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:

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. Install dependencies into a virtual environment, an isolated folder containing only the packages this project needs.

Create one in the project folder and activate it:

python3 -m venv .venv
source .venv/bin/activate

The prompt now starts with (.venv). Install the project's dependencies:

pip install -r requirements.txt

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. When using systemd for autostart (see below), point ExecStart directly at the interpreter inside .venv, no activation step needed:

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

Other runtimes​

For other languages or dependency managers, the project README is the reference. The pattern is the same: 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 first.

What is tmux?​

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

Install tmux​

sudo apt update && sudo apt install tmux -y
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.

Make the start script executable (if needed)​

If the project includes a start.sh:

chmod +x start.sh

See Terminal basics for what this does.

Start a tmux session​

tmux new -s app

The terminal is now inside a tmux session. A status bar at the bottom shows the session name.

Start the application​

Run the project's start command, for example ./start.sh, node server.js or python app.py. The startup output appears in the terminal.

Detach from the session​

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

Re-attach to the session​

To inspect or stop the application later:

tmux attach -t app

To list all running sessions:

tmux ls

Restart automatically on reboot​

tmux sessions do not survive a device reboot. Use systemd to start the application 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

Check the status with sudo systemctl status myapp. With Power Mode on, the unit also shows up in the device's Services tab, where you can start, stop and restart it from the dashboard.

Point a domain at the port​

Once the application is running, note its port from the start output, the README or the ports: section of docker-compose.yml. A line such as Server listening on http://localhost:3000 means port 3000.

Then open the device's Hosting tab in Obacht, add a domain if you have none yet, and bind it to the port instead of an app instance. The device's Caddy gets a certificate and routes the domain to your process. The step-by-step flow is on Point an address at a port.

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