Install · Manual setup

Run the storefront as a service

This page sets up by hand what orionplace app install and the storefront's install command do: a system user, the production build and a service that starts the storefront at boot and restarts it after a failure. The files below are the ones the installer writes, for a storefront named shop in /srv/orionplace/shop on port 3000.

How it works

The storefront is a Node.js server. It listens only on 127.0.0.1, so only this server reaches it; nginx takes the public HTTPS requests and passes them to it, see nginx configuration. For each request the storefront picks your personal backend by the request's domain, from the domain files in the project.

1 Requirements

SvelteKit storefronts need Node.js 20.19 or newer; the server tool installs Node.js 24 LTS. Check the installed version:

bash
node -v

You also need npm, root access and a Linux server with systemd (Debian, Ubuntu, the RHEL family, Fedora, openSUSE, Arch) or OpenRC (Alpine). The service files below start /usr/local/bin/node; if command -v node shows another path, use that one.

2 Service user and folder

The storefront runs as its own system user without a login shell, so it can change only its own folder. Every parent folder of the storefront must be open to this user; /srv/orionplace is.

bash
sudo useradd --system --home-dir /srv/orionplace \
  --shell /sbin/nologin --user-group orionplace
sudo mkdir -p /srv/orionplace
sudo chown orionplace:orionplace /srv/orionplace

On Alpine, which has no useradd:

bash
sudo addgroup -S orionplace
sudo adduser -S -D -H -h /srv/orionplace -s /sbin/nologin -G orionplace orionplace

3 Create and connect the storefront

Create the project, set your personal backend and add the storefront domain. Your personal backend is shown in your orionmarket.place profile.

bash
cd /srv/orionplace
sudo npx --yes orionplace-svelte init shop
cd shop
sudo npm install
sudo npx orionplace-svelte set backend my-shop.orionplace.app
sudo npx orionplace-svelte add frontend shop.example.com

set backend and add frontend write .env and the domain files the storefront reads for each request. A domain that is not added gets the answer 503: the storefront never falls back to another domain.

4 Build

Build the production server, then give the folder to the service user. Build again after every change.

bash
cd /srv/orionplace/shop
sudo npm run build
sudo chown -R orionplace:orionplace /srv/orionplace/shop

To try the build, start it by hand in the same folder and stop it with Ctrl+C:

bash
sudo -u orionplace env HOST=127.0.0.1 PORT=3000 PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host ADDRESS_HEADER=x-real-ip BODY_SIZE_LIMIT=67108864 /usr/local/bin/node --env-file=.env build/index.js

5 Environment

The service sets these variables. Your own settings go to .env in the project folder.

VariableWhat it does
NODE_ENVRuns the production build.
HOSTThe address the server listens on. 127.0.0.1 keeps the port closed to the internet; only nginx on this server reaches it.
PORTThe port nginx passes requests to. Give each storefront on the server its own port.
SITEMAPS_DIRFull path of the project's sitemaps folder, so the server finds it from any working folder.
.envRead with --env-file=.env: the project's own settings, such as MIMIC_FRONT_DOMAIN for local runs. Public domains take priority over it.
PROTOCOL_HEADERSvelteKit: take the protocol from X-Forwarded-Proto, which nginx sets.
HOST_HEADERSvelteKit: take the domain from X-Forwarded-Host.
ADDRESS_HEADERSvelteKit: take the customer's address from X-Real-IP.
BODY_SIZE_LIMITSvelteKit: accept request bodies up to 64 MB, such as review photos, avatars and attachments; its default is 512 KB.

6 systemd service

On a system with systemd, save this file:

/etc/systemd/system/orionplace-shop.service
# Installed by "orionplace-svelte install". Run it again after changes;
# manage with: orionplace app status|logs|restart shop
[Unit]
Description=OrionMarketplace storefront shop (SvelteKit)
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=orionplace
Group=orionplace
WorkingDirectory=/srv/orionplace/shop
Environment=NODE_ENV=production
Environment=HOST=127.0.0.1
Environment=PORT=3000
Environment=SITEMAPS_DIR=/srv/orionplace/shop/sitemaps
Environment=PROTOCOL_HEADER=x-forwarded-proto
Environment=HOST_HEADER=x-forwarded-host
Environment=ADDRESS_HEADER=x-real-ip
Environment=BODY_SIZE_LIMIT=67108864
ExecStart=/usr/local/bin/node --env-file=.env build/index.js
Restart=on-failure
RestartSec=3
LimitNOFILE=65535
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target

Load it, start the storefront now and at every boot, then check it and read its log:

bash
sudo systemctl daemon-reload
sudo systemctl enable --now orionplace-shop
sudo systemctl status orionplace-shop
sudo journalctl -u orionplace-shop -n 50

7 OpenRC service (Alpine)

On Alpine, save this script instead:

/etc/init.d/orionplace-shop
#!/sbin/openrc-run
# Installed by "orionplace-svelte install". Run it again after changes;
# manage with: orionplace app status|logs|restart shop
name="orionplace-shop"
description="OrionMarketplace storefront shop (SvelteKit)"
supervisor=supervise-daemon
respawn_delay=3
command="/usr/local/bin/node"
command_args="--env-file=.env build/index.js"
command_user="orionplace:orionplace"
directory="/srv/orionplace/shop"
output_log="/var/log/orionplace/shop.log"
error_log="/var/log/orionplace/shop.log"
export NODE_ENV="production"
export HOST="127.0.0.1"
export PORT="3000"
export SITEMAPS_DIR="/srv/orionplace/shop/sitemaps"
export PROTOCOL_HEADER="x-forwarded-proto"
export HOST_HEADER="x-forwarded-host"
export ADDRESS_HEADER="x-real-ip"
export BODY_SIZE_LIMIT="67108864"

depend() {
  need net
  after firewall
}

start_pre() {
  checkpath --directory --owner orionplace:orionplace --mode 0755 /var/log/orionplace
}

Make it executable, start it now and at every boot, then read its log:

bash
sudo chmod 755 /etc/init.d/orionplace-shop
sudo rc-update add orionplace-shop default
sudo rc-service orionplace-shop start
sudo tail -n 50 /var/log/orionplace/shop.log

8 Check the service

Ask the storefront for its home page as your domain:

bash
curl -sI -H 'Host: shop.example.com' http://127.0.0.1:3000/

HTTP/1.1 200 means the storefront works. 503 means the domain is not added to the project. No answer means the service is not running: read its log. Then publish the storefront over HTTPS, see nginx configuration.

9 Updates

Update the storefront package, build and restart the service (on Alpine: sudo rc-service orionplace-shop restart):

bash
cd /srv/orionplace/shop
sudo npx orionplace-svelte update
sudo npm run build
sudo chown -R orionplace:orionplace /srv/orionplace/shop
sudo systemctl restart orionplace-shop

To hand the storefront over to the tools later, run its install command in the folder. It writes the same service file over yours and connects the domains through the server tool, once the tool is set up. Remove your own nginx file of the domain first: the tool does not take a domain that another file serves.

bash
cd /srv/orionplace/shop
sudo npx orionplace-svelte install