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:
node -vYou 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.
sudo useradd --system --home-dir /srv/orionplace \
--shell /sbin/nologin --user-group orionplace
sudo mkdir -p /srv/orionplace
sudo chown orionplace:orionplace /srv/orionplaceOn Alpine, which has no useradd:
sudo addgroup -S orionplace
sudo adduser -S -D -H -h /srv/orionplace -s /sbin/nologin -G orionplace orionplace3 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.
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.comset 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.
cd /srv/orionplace/shop
sudo npm run build
sudo chown -R orionplace:orionplace /srv/orionplace/shopTo try the build, start it by hand in the same folder and stop it with Ctrl+C:
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.js5 Environment
The service sets these variables. Your own settings go to .env in the project folder.
| Variable | What it does |
|---|---|
NODE_ENV | Runs the production build. |
HOST | The address the server listens on. 127.0.0.1 keeps the port closed to the internet; only nginx on this server reaches it. |
PORT | The port nginx passes requests to. Give each storefront on the server its own port. |
SITEMAPS_DIR | Full path of the project's sitemaps folder, so the server finds it from any working folder. |
.env | Read with --env-file=.env: the project's own settings, such as MIMIC_FRONT_DOMAIN for local runs. Public domains take priority over it. |
PROTOCOL_HEADER | SvelteKit: take the protocol from X-Forwarded-Proto, which nginx sets. |
HOST_HEADER | SvelteKit: take the domain from X-Forwarded-Host. |
ADDRESS_HEADER | SvelteKit: take the customer's address from X-Real-IP. |
BODY_SIZE_LIMIT | SvelteKit: 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:
# 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:
sudo systemctl daemon-reload
sudo systemctl enable --now orionplace-shop
sudo systemctl status orionplace-shop
sudo journalctl -u orionplace-shop -n 507 OpenRC service (Alpine)
On Alpine, save this script instead:
#!/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:
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.log8 Check the service
Ask the storefront for its home page as your domain:
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):
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-shopTo 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.
cd /srv/orionplace/shop
sudo npx orionplace-svelte install