---
title: "Deploy OpenSourcePOS | (Just Updated) Open Source Point of Sale for Retail, MariaDB Included, Admin Pre-Set"
description: "OpenSourcePOS point of sale software: retail POS, inventory, self-hosted"
category: "Other"
url: https://railway.com/deploy/opensourcepos-or-just-updated-open-sourc
---

# Deploy OpenSourcePOS | (Just Updated) Open Source Point of Sale for Retail, MariaDB Included, Admin Pre-Set

OpenSourcePOS point of sale software: retail POS, inventory, self-hosted

**[Deploy OpenSourcePOS | (Just Updated) Open Source Point of Sale for Retail, MariaDB Included, Admin Pre-Set on Railway](https://railway.com/template/opensourcepos-or-just-updated-open-sourc)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/opensourcepos-or-just-updated-open-sourc/manifest.json

- **Creator:** SuperSlowSloth
- **Category:** Other

## Template content

### mariadb

- **Image:** ghcr.io/bon5co/opensourcepos-railway-mariadb:11.8.2@sha256:f261b86c34cac16af4e1e5380c7d2ef8c9af26c3b9eb5600bf7c17bc185a2581

### opensourcepos

- **Image:** ghcr.io/bon5co/opensourcepos-railway:3.4.3@sha256:a5752843119ca03454ecf9ab340320b6c90e3496df7d56e41428c06202f93ca4
- **Health check:** /login
- **Public domain:** Yes

## Documentation

# Deploy and Host OpenSourcePOS on Railway

**Built for an LLM agent to deploy and use.** The deploy form has no fields. OpenSourcePOS, the open-source web point of sale for retail (sales register, inventory, customers, suppliers, receipts, reports), comes up with a MariaDB database, an administrator account already created from a generated password, and a public HTTPS address. The contract below lists every address, variable name and one script that logs in and creates a customer.

OpenSourcePOS here is the official `jekkos/opensourcepos` image, version 3.4.3 (CodeIgniter 4, PHP 8.2, Apache), behind a thin wrapper pinned by digest.

## About Hosting OpenSourcePOS

This template runs two services: OpenSourcePOS (wrapper image) and MariaDB 11.8. On every boot the wrapper binds Apache to Railway's port, waits for MariaDB, runs the database migrations, generates the application encryption keys once and stores them on the volume, and replaces the factory login `admin` / `pointofsale` with the password in `ADMIN_PASSWORD` while the account still has the factory password. Redeploys keep the keys, the sessions and the data.

Two details matter on Railway. The edge address rotates between requests, so the wrapper turns off the application's IP-bound sessions; without that, every login is thrown back to the login page. And the shop's uploads live on the `/data` volume.

### Agent contract

- Public URL: `https://` plus the `RAILWAY_PUBLIC_DOMAIN` value of the `opensourcepos` service (the web application at `/`)
- Private URL: `http://opensourcepos.railway.internal:8080`
- Credentials: `ADMIN_PASSWORD` (password of the user `admin`, generated, 32 characters); `MYSQL_PASSWORD` and `MYSQL_HOST_NAME` are internal and need not be handled
- Auth: session cookie. `POST /login` with form fields `username=admin` and `password` answers 303 and sets the `ospos_session` cookie; writes also send the CSRF token (form field `csrf_ospos_v4`, the 32 hex characters printed in the page script of `/customers`)
- Health: `GET /login` returns 200 without authentication; with the header `X-Requested-With: XMLHttpRequest`, `POST /customers/save/-1` without a session returns 401 (write without key: 401)

```bash
# needs: HOST (RAILWAY_PUBLIC_DOMAIN of the opensourcepos service) and ADMIN_PASSWORD from its variables
BASE="https://$HOST"
J=$(mktemp)
curl -s -o /dev/null -w "health: %{http_code}\n" "$BASE/login"
curl -s -o /dev/null -w "write without key: %{http_code}\n" -X POST -H 'X-Requested-With: XMLHttpRequest' -d 'first_name=x' "$BASE/customers/save/-1"
curl -s -c "$J" -b "$J" -o /dev/null "$BASE/login"
curl -s -c "$J" -b "$J" -o /dev/null -w "login: %{http_code}\n" --data-urlencode username=admin --data-urlencode "password=$ADMIN_PASSWORD" "$BASE/login"
curl -s -c "$J" -b "$J" -o /dev/null -w "read with key: %{http_code}\n" "$BASE/home"
T=$(curl -s -c "$J" -b "$J" "$BASE/customers" | sed -n 's/.*return "\([0-9a-f]\{32\}\)".*/\1/p' | head -1)
curl -s -c "$J" -b "$J" -H 'X-Requested-With: XMLHttpRequest' -w "\ncreate customer: %{http_code}\n" -X POST \
  --data-urlencode "csrf_ospos_v4=$T" --data-urlencode first_name=Agent --data-urlencode last_name=Test \
  --data-urlencode email=agent@example.com --data-urlencode gender=1 --data-urlencode 'date=11/08/2026 12:00:00' \
  --data-urlencode employee_id=1 --data-urlencode phone_number= --data-urlencode address_1= --data-urlencode address_2= \
  --data-urlencode city= --data-urlencode state= --data-urlencode zip= --data-urlencode country= --data-urlencode comments= \
  --data-urlencode tax_id= --data-urlencode discount= --data-urlencode account_number= "$BASE/customers/save/-1"
rm -f "$J"
```

A fresh deploy prints `health: 200`, `write without key: 401`, `login: 303`, `read with key: 200`, then a JSON line with `"success":true` and `create customer: 200`. Running it again adds another customer with the same result.

## Why Deploy OpenSourcePOS on Railway?

Railway is a singular platform to deploy your infrastructure stack. Railway will host your infrastructure so you don't have to deal with configuration, while allowing you to vertically and horizontally scale it.

By deploying OpenSourcePOS on Railway, you are one step closer to supporting a complete full-stack application with minimal burden. Host your servers, databases, AI agents, and more on Railway.

- **Agent-ready** - no deployer fields, a contract block and one working login-and-create script.
- **Admin pre-set** - the factory `admin` / `pointofsale` login is replaced at first boot by a generated password, so a fresh shop is never left on a public default.
- **Logins that stick** - IP-bound sessions are off, so the rotating Railway edge address does not bounce you back to the login page.
- **Persistent** - MariaDB, uploads and the application keys sit on volumes and survive redeploys.

## Common Use Cases

- **Run a small shop's register** with barcode sales, receipts, discounts and cash-up.
- **Track stock** across items, suppliers and receivings, with low-stock reports.
- **Keep a customer list** with loyalty discounts and sales history.
- **Point of sale API for your own code** - drive the same web endpoints from a script or an AI agent.

## Dependencies for OpenSourcePOS Hosting

- MariaDB (included as the `mariadb` service)

### Deployment Dependencies

- [OpenSourcePOS repository](https://github.com/opensourcepos/opensourcepos)
- [OpenSourcePOS website](https://opensourcepos.org)
- [Wrapper image source](https://github.com/bon5co/opensourcepos-railway)

### Implementation Details

| Variable | Purpose |
| --- | --- |
| `ADMIN_PASSWORD` | Generated password of the user `admin`. Applied only while the account still has the factory password. |
| `MYSQL_HOST_NAME` | Private address of the `mariadb` service. |
| `MYSQL_PASSWORD` | Database password, shared with the `mariadb` service as `MARIADB_PASSWORD`. |

The service listens on Railway's `PORT` (8080). The date and time format in the script above is the OpenSourcePOS default (`m/d/Y H:i:s`); if you change it under Configuration, send the customer `date` field in the new format.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/opensourcepos-or-just-updated-open-sourc
