Vexon Commerce

Installing Vexon Commerce

Get Vexon Commerce running on your own server, from a fresh Linux box to your first sign-in.

InstallingLast checked

Before you start

You'll need a Linux server with Docker, a domain name and the services in What you need: PostgreSQL, Meilisearch, S3-compatible storage, imgproxy and email sending. This guide builds the image from the code and runs it with docker run. The examples use shop.example.com for your shop's address.

Install it

  1. 1

    Get the code

    We share the code when you get in touch. Put it on your server in a folder of its own, such as /opt/vexon-commerce.

  2. 2

    Build the image

    There's no published image yet, so you build your own from the Dockerfile in the code. The first build takes a while.

    Terminal
    $ cd /opt/vexon-commerce$ docker build -t vexon-commerce .

    The image expects imgproxy at /img on your media address. If you're not using imgproxy, build with --build-arg NEXT_PUBLIC_IMAGE_PROXY_PATH= instead, and photos are served as they are.

  3. 3

    Create your settings file

    Everything the app needs to find your database, search, storage and email lives in one file, .env. Copy the example, then fill it in using the settings below. It holds passwords and keys, so keep it readable only by you, and keep a copy somewhere safe.

    Terminal
    $ cp .env.example .env$ chmod 600 .env

    Write every value without quotes, as KEY=value. Docker keeps quote marks as part of the value, so a line like KEY="value" fails when the app starts. If you copy a line from the example that has quotes, remove them.

    .env
    DATABASE_URL=postgres://shop:secret@db:5432/shop
    DIRECT_URL=postgres://shop:secret@db:5432/shop
    [email protected]
  4. 4

    Describe your shop

    Describe your shop in a small file: its name, address on the web, currency, tax and the owner's email. Save it next to .env as your-shop.json.

    your-shop.json
    {
      "name": "Your Shop",
      "slug": "your-shop",
      "ownerEmail": "[email protected]",
      "defaultLocale": "en-GB",
      "baseCurrency": "GBP",
      "countryCode": "GB",
      "timezone": "Europe/London",
      "taxMode": "INCLUSIVE",
      "domains": [{ "host": "shop.example.com", "isPrimary": true }],
      "settings": { "legalName": "Your Shop Ltd" },
      "shipping": { "flatRateMinor": 499 },
      "tax": { "domesticRateBps": 2000 },
      "featureFlags": { "checkout": false }
    }

    slug is a short name in lowercase with hyphens. Prices are in the smallest unit, so 499 is £4.99, and tax is in hundredths of a percent, so 2000 is 20%. The settings file reference lists every option.

  5. 5

    Create the shop

    Run these once, before you start the app for real. The first prepares the database. The second creates your shop and its owner account.

    Terminal
    $ docker run --rm --env-file .env vexon-commerce \    npm exec -- prisma migrate deploy$ docker run --rm --env-file .env \    -v "$PWD/your-shop.json:/app/your-shop.json:ro" \    vexon-commerce npm run provision:site -- your-shop.json

    It finishes with "Set SINGLE_STORE_SLUG=your-shop". Add that line to .env. You can run it again safely if you change the file, but switches are only set the first time.

  6. 6

    Start it

    --restart unless-stopped brings it back after a reboot. Each start brings the database up to date, then checks every page before it opens, so give it a minute.

    Terminal
    $ docker run -d --name vexon-commerce \    --restart unless-stopped \    --env-file .env -p 3000:3000 vexon-commerce
  7. 7

    Put it behind your domain

    Point your domain at the server. Then add a reverse proxy with HTTPS that forwards to port 3000 and passes the Host and X-Forwarded-* headers through. Check .env has AUTH_URL set to your shop's address and AUTH_TRUST_HOST=true; if you change it, restart the container. Check it from anywhere:

    Terminal
    $ curl -s https://shop.example.com/api/health
  8. 8

    Schedule the background jobs

    Nothing is emailed until something calls the app's job routes. Add a cron job, or any scheduler, that makes these requests. The email job is the one that sends order emails and password resets, so it must run every minute. Open your crontab with crontab -e and add:

    crontab
    * * * * * curl -fsS -X POST -H "Authorization: Bearer EMAIL_WORKER_SECRET_HERE" https://shop.example.com/api/jobs/email
    */5 * * * * curl -fsS -X POST -H "Authorization: Bearer CRON_SECRET_HERE" https://shop.example.com/api/jobs/release-expired-reservations
    23 * * * * curl -fsS -X POST -H "Authorization: Bearer CRON_SECRET_HERE" https://shop.example.com/api/jobs/process-data-requests

    Use your own EMAIL_WORKER_SECRET and CRON_SECRET from .env. These three can't be missed. The full list of jobs and how often each one runs is in scripts/cron/schedule.json in the code. Settings › Jobs in the admin shows when each one last ran.

  9. 9

    Build the search index

    Terminal
    $ docker exec vexon-commerce npm run search:reindex
  10. 10

    Set the owner's password

    Go to /admin on your domain. It takes you to Sign in. Choose Forgotten your password?, enter the owner's email from your shop file, and use the link in the email to set a password. The link works for 30 minutes.

Settings

These must be set before the app will start. The configuration settings list everything else, with defaults.

NameWhat it doesExample
DATABASE_URL

Where your PostgreSQL database is.

postgres://shop:…@db:5432/shop
DIRECT_URL

The same as DATABASE_URL, unless you put a connection pooler in front of PostgreSQL. Needed to prepare the database.

postgres://shop:…@db:5432/shop
AUTH_SECRET

Keeps sign-ins secure.

a long random string
AUTH_SECRETS_KEY

Encrypts two-factor and webhook secrets. Losing it locks staff out of two-factor.

at least 32 random characters
AUTH_URL

Your shop's address.

https://shop.example.com
EMAIL_WORKER_SECRET

Lets your scheduler send the email queue.

at least 16 random characters
CRON_SECRET

Lets your scheduler run the other jobs.

at least 16 random characters
SES_SNS_WEBHOOK_SECRET, SES_SNS_ALLOWED_TOPIC_ARN

For delivery and bounce reports from Amazon SES. Both are required.

a random string, your SNS topic
MEILISEARCH_HOST, MEILISEARCH_API_KEY

Your Meilisearch server and its key.

http://search:7700
S3_ENDPOINT, S3_BUCKET

Your storage and the bucket for photos and uploads.

https://s3.example.com, shop-media
S3_ACCESS_KEY, S3_SECRET_KEY

Keys for that bucket.

from your storage provider
MEDIA_CDN_BASE_URL

The public address of your bucket, ending in the bucket name.

https://media.example.com/shop-media
EMAIL_FROM

Who emails come from. Just the address: emails use your shop's name as the sender name.

[email protected]
SINGLE_STORE_SLUG

Your shop's slug, from step 5.

your-shop

Switch features on

Many features ship switched off. Most are turned on by the shop owner in AdminthenSettingsthenFeature flags. Seven can only be set in your shop's file, under featureFlags, the first time you create the shop, because they change how money is taken or what's recorded. Later runs of provision:site leave them alone.

SwitchWhat it doesDefault
checkout

Turns on checkout. Needs live Stripe keys and a sender email.

false
multiCurrency

Lets shoppers pay in their own currency.

false
regionalPricing

Regional price overrides.

false
reservations

Holds stock for 15 minutes while a shopper pays, so two people can't buy the last one.

false
newsletterDoubleOptIn

Newsletter sign-ups confirm by email.

true
consentBanner

Shows the cookie consent banner.

true
analyticsCapture

First-party analytics, recorded by the shop itself.

true

Keeping it updated

Nothing updates itself. When a new version is out, you choose when to install it: back up the database and storage, rebuild the image, then restart. See Updating Vexon Commerce.

Was this helpful?