Dokploy

OpenSourcePOS

OpenSourcePOS is a web-based point of sale system for managing sales, inventory, customers, and reports.

OpenSourcePOS logo

Configuration

version: "3.8"

services:
  opensourcepos:
    image: jekkos/opensourcepos:master
    restart: unless-stopped
    depends_on:
      opensourcepos-db:
        condition: service_healthy
    expose:
      - "80"
    environment:
      CI_ENVIRONMENT: production
      ALLOWED_HOSTNAMES: ${ALLOWED_HOSTNAMES}
      FORCE_HTTPS: ${FORCE_HTTPS}
      PHP_TIMEZONE: ${PHP_TIMEZONE}
      MYSQL_USERNAME: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DB_NAME: ${MYSQL_DATABASE}
      MYSQL_HOST_NAME: opensourcepos-db
    volumes:
      - opensourcepos-uploads:/app/public/uploads
      - opensourcepos-logs:/app/writable/logs

  opensourcepos-db:
    image: mariadb:10.11
    restart: unless-stopped
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${MYSQL_DATABASE}
      MYSQL_USER: ${MYSQL_USER}
      MYSQL_PASSWORD: ${MYSQL_PASSWORD}
    volumes:
      - opensourcepos-db:/var/lib/mysql
    healthcheck:
      test: ["CMD-SHELL", "healthcheck.sh --connect --innodb_initialized"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s

volumes:
  opensourcepos-db:
  opensourcepos-uploads:
  opensourcepos-logs:
[variables]
main_domain = "${domain}"
mysql_root_password = "${password:32}"
mysql_password = "${password:32}"
php_timezone = "UTC"
force_https = "false"
allowed_hostnames = "${main_domain}"

[[config.domains]]
serviceName = "opensourcepos"
port = 80
host = "${main_domain}"
path = "/"

[[config.mounts]]
filePath = "README.md"
content = """# OpenSourcePOS

This template deploys Open Source Point of Sale with MariaDB using the upstream Docker image and persistent storage for uploads, logs, and database data.

## Access

- URL: `http://${main_domain}`
- Default application user: `admin`
- Default application password: `pointofsale`

Change the default application password immediately after the first login.

## Hostnames and HTTPS

OpenSourcePOS validates incoming host headers in production. The `allowed_hostnames` variable defaults to `${main_domain}` and can be set to a comma-separated list such as `pos.example.com,www.pos.example.com`.

The template defaults `force_https` to `false` because Dokploy terminates TLS outside the container. Set it to `true` only when your deployment always reaches OpenSourcePOS through HTTPS and the reverse proxy sends the expected headers.

## Storage

The template creates persistent volumes for:

- MariaDB data
- uploaded files
- application logs
"""

[config.env]
MYSQL_ROOT_PASSWORD = "${mysql_root_password}"
MYSQL_DATABASE = "ospos"
MYSQL_USER = "admin"
MYSQL_PASSWORD = "${mysql_password}"
PHP_TIMEZONE = "${php_timezone}"
FORCE_HTTPS = "${force_https}"
ALLOWED_HOSTNAMES = "${allowed_hostnames}"

Base64

To import this template in Dokploy: create a Compose service → AdvancedBase64 import and paste the content below:

ewogICJjb21wb3NlIjogInZlcnNpb246IFwiMy44XCJcblxuc2VydmljZXM6XG4gIG9wZW5zb3VyY2Vwb3M6XG4gICAgaW1hZ2U6IGpla2tvcy9vcGVuc291cmNlcG9zOm1hc3RlclxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgZGVwZW5kc19vbjpcbiAgICAgIG9wZW5zb3VyY2Vwb3MtZGI6XG4gICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5XG4gICAgZXhwb3NlOlxuICAgICAgLSBcIjgwXCJcbiAgICBlbnZpcm9ubWVudDpcbiAgICAgIENJX0VOVklST05NRU5UOiBwcm9kdWN0aW9uXG4gICAgICBBTExPV0VEX0hPU1ROQU1FUzogJHtBTExPV0VEX0hPU1ROQU1FU31cbiAgICAgIEZPUkNFX0hUVFBTOiAke0ZPUkNFX0hUVFBTfVxuICAgICAgUEhQX1RJTUVaT05FOiAke1BIUF9USU1FWk9ORX1cbiAgICAgIE1ZU1FMX1VTRVJOQU1FOiAke01ZU1FMX1VTRVJ9XG4gICAgICBNWVNRTF9QQVNTV09SRDogJHtNWVNRTF9QQVNTV09SRH1cbiAgICAgIE1ZU1FMX0RCX05BTUU6ICR7TVlTUUxfREFUQUJBU0V9XG4gICAgICBNWVNRTF9IT1NUX05BTUU6IG9wZW5zb3VyY2Vwb3MtZGJcbiAgICB2b2x1bWVzOlxuICAgICAgLSBvcGVuc291cmNlcG9zLXVwbG9hZHM6L2FwcC9wdWJsaWMvdXBsb2Fkc1xuICAgICAgLSBvcGVuc291cmNlcG9zLWxvZ3M6L2FwcC93cml0YWJsZS9sb2dzXG5cbiAgb3BlbnNvdXJjZXBvcy1kYjpcbiAgICBpbWFnZTogbWFyaWFkYjoxMC4xMVxuICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkXG4gICAgZW52aXJvbm1lbnQ6XG4gICAgICBNWVNRTF9ST09UX1BBU1NXT1JEOiAke01ZU1FMX1JPT1RfUEFTU1dPUkR9XG4gICAgICBNWVNRTF9EQVRBQkFTRTogJHtNWVNRTF9EQVRBQkFTRX1cbiAgICAgIE1ZU1FMX1VTRVI6ICR7TVlTUUxfVVNFUn1cbiAgICAgIE1ZU1FMX1BBU1NXT1JEOiAke01ZU1FMX1BBU1NXT1JEfVxuICAgIHZvbHVtZXM6XG4gICAgICAtIG9wZW5zb3VyY2Vwb3MtZGI6L3Zhci9saWIvbXlzcWxcbiAgICBoZWFsdGhjaGVjazpcbiAgICAgIHRlc3Q6IFtcIkNNRC1TSEVMTFwiLCBcImhlYWx0aGNoZWNrLnNoIC0tY29ubmVjdCAtLWlubm9kYl9pbml0aWFsaXplZFwiXVxuICAgICAgaW50ZXJ2YWw6IDEwc1xuICAgICAgdGltZW91dDogNXNcbiAgICAgIHJldHJpZXM6IDVcbiAgICAgIHN0YXJ0X3BlcmlvZDogMzBzXG5cbnZvbHVtZXM6XG4gIG9wZW5zb3VyY2Vwb3MtZGI6XG4gIG9wZW5zb3VyY2Vwb3MtdXBsb2FkczpcbiAgb3BlbnNvdXJjZXBvcy1sb2dzOlxuIiwKICAiY29uZmlnIjogIlt2YXJpYWJsZXNdXG5tYWluX2RvbWFpbiA9IFwiJHtkb21haW59XCJcbm15c3FsX3Jvb3RfcGFzc3dvcmQgPSBcIiR7cGFzc3dvcmQ6MzJ9XCJcbm15c3FsX3Bhc3N3b3JkID0gXCIke3Bhc3N3b3JkOjMyfVwiXG5waHBfdGltZXpvbmUgPSBcIlVUQ1wiXG5mb3JjZV9odHRwcyA9IFwiZmFsc2VcIlxuYWxsb3dlZF9ob3N0bmFtZXMgPSBcIiR7bWFpbl9kb21haW59XCJcblxuW1tjb25maWcuZG9tYWluc11dXG5zZXJ2aWNlTmFtZSA9IFwib3BlbnNvdXJjZXBvc1wiXG5wb3J0ID0gODBcbmhvc3QgPSBcIiR7bWFpbl9kb21haW59XCJcbnBhdGggPSBcIi9cIlxuXG5bW2NvbmZpZy5tb3VudHNdXVxuZmlsZVBhdGggPSBcIlJFQURNRS5tZFwiXG5jb250ZW50ID0gXCJcIlwiIyBPcGVuU291cmNlUE9TXG5cblRoaXMgdGVtcGxhdGUgZGVwbG95cyBPcGVuIFNvdXJjZSBQb2ludCBvZiBTYWxlIHdpdGggTWFyaWFEQiB1c2luZyB0aGUgdXBzdHJlYW0gRG9ja2VyIGltYWdlIGFuZCBwZXJzaXN0ZW50IHN0b3JhZ2UgZm9yIHVwbG9hZHMsIGxvZ3MsIGFuZCBkYXRhYmFzZSBkYXRhLlxuXG4jIyBBY2Nlc3NcblxuLSBVUkw6IGBodHRwOi8vJHttYWluX2RvbWFpbn1gXG4tIERlZmF1bHQgYXBwbGljYXRpb24gdXNlcjogYGFkbWluYFxuLSBEZWZhdWx0IGFwcGxpY2F0aW9uIHBhc3N3b3JkOiBgcG9pbnRvZnNhbGVgXG5cbkNoYW5nZSB0aGUgZGVmYXVsdCBhcHBsaWNhdGlvbiBwYXNzd29yZCBpbW1lZGlhdGVseSBhZnRlciB0aGUgZmlyc3QgbG9naW4uXG5cbiMjIEhvc3RuYW1lcyBhbmQgSFRUUFNcblxuT3BlblNvdXJjZVBPUyB2YWxpZGF0ZXMgaW5jb21pbmcgaG9zdCBoZWFkZXJzIGluIHByb2R1Y3Rpb24uIFRoZSBgYWxsb3dlZF9ob3N0bmFtZXNgIHZhcmlhYmxlIGRlZmF1bHRzIHRvIGAke21haW5fZG9tYWlufWAgYW5kIGNhbiBiZSBzZXQgdG8gYSBjb21tYS1zZXBhcmF0ZWQgbGlzdCBzdWNoIGFzIGBwb3MuZXhhbXBsZS5jb20sd3d3LnBvcy5leGFtcGxlLmNvbWAuXG5cblRoZSB0ZW1wbGF0ZSBkZWZhdWx0cyBgZm9yY2VfaHR0cHNgIHRvIGBmYWxzZWAgYmVjYXVzZSBEb2twbG95IHRlcm1pbmF0ZXMgVExTIG91dHNpZGUgdGhlIGNvbnRhaW5lci4gU2V0IGl0IHRvIGB0cnVlYCBvbmx5IHdoZW4geW91ciBkZXBsb3ltZW50IGFsd2F5cyByZWFjaGVzIE9wZW5Tb3VyY2VQT1MgdGhyb3VnaCBIVFRQUyBhbmQgdGhlIHJldmVyc2UgcHJveHkgc2VuZHMgdGhlIGV4cGVjdGVkIGhlYWRlcnMuXG5cbiMjIFN0b3JhZ2VcblxuVGhlIHRlbXBsYXRlIGNyZWF0ZXMgcGVyc2lzdGVudCB2b2x1bWVzIGZvcjpcblxuLSBNYXJpYURCIGRhdGFcbi0gdXBsb2FkZWQgZmlsZXNcbi0gYXBwbGljYXRpb24gbG9nc1xuXCJcIlwiXG5cbltjb25maWcuZW52XVxuTVlTUUxfUk9PVF9QQVNTV09SRCA9IFwiJHtteXNxbF9yb290X3Bhc3N3b3JkfVwiXG5NWVNRTF9EQVRBQkFTRSA9IFwib3Nwb3NcIlxuTVlTUUxfVVNFUiA9IFwiYWRtaW5cIlxuTVlTUUxfUEFTU1dPUkQgPSBcIiR7bXlzcWxfcGFzc3dvcmR9XCJcblBIUF9USU1FWk9ORSA9IFwiJHtwaHBfdGltZXpvbmV9XCJcbkZPUkNFX0hUVFBTID0gXCIke2ZvcmNlX2h0dHBzfVwiXG5BTExPV0VEX0hPU1ROQU1FUyA9IFwiJHthbGxvd2VkX2hvc3RuYW1lc31cIlxuIgp9

Tags

pos, retail, inventory, sales, business


Version: master

On this page