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:
- The application runs on the device and listens on a port (for example
3000). - In the device's Hosting tab, a domain is bound to that port.
- 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
Navigate to the project
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.
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
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.
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
| Task | Command |
|---|---|
| Start containers in background | docker compose up -d |
| Check container status | docker compose ps |
| Follow container logs | docker compose logs -f |
| Stop containers | docker compose down |
| Start a new tmux session | tmux new -s app |
| Detach from tmux | Ctrl + B, then D |
| Re-attach to tmux session | tmux attach -t app |
| List tmux sessions | tmux ls |
| Enable app to start on boot | sudo systemctl enable myapp |
| Check systemd service status | sudo systemctl status myapp |