All documents

Setup guide

SmartMarket: setting up your own copy

Start a new machine from a snapshot of the shop, give it its own address, and check it in your browser. No prior server experience assumed.

Abad Naseer  ·  17 August 2026  ·  every command run against the live server

1. What this guide is for

You have a working shop, SmartMarket, running on one machine. This guide takes a photograph of that machine, starts a second one from the photograph, and gives the second one its own web address.

Nothing gets built. The copy arrives finished and already running. The work is telling it its new name.

The shop this copy is made from: https://marketz.smartzees.com

Every command below was run against the live machines. Wherever a command appears, the line under it says what you should see when it worked. If you see something else, that is where to stop and look.


2. How the shop is put together

One machine, four parts

Four parts, all on one machine.

PartIts job
nginxThe front door. The only part open to the internet.
The shop pagesPlain files. No program running.
The applicationAnswers anything under /api/.
The catalogueMySQL, on the same machine. 25,701 products.

Four places the commands below refer to:

ThingWhere it lives
The application/var/www/ai-order/backend, service name aiorder
The shop pages/var/www/ai-order/frontend-dist
The settings file/var/www/ai-order/backend/.env
The front door file/etc/nginx/sites-available/aiorder-dev

3. Making your own copy

Your own copy: the whole journey

Six stages, about half an hour. Most of it is waiting for the new web address to spread across the internet.

Stage 1: Take the photograph

In the Lightsail console, open the shop's instance, go to the Snapshots tab and press Create snapshot. Give it today's date as a name.

Nothing stops. Customers on the live shop notice nothing. It takes a few minutes because the disk is about 31 GB.

You should see: the snapshot in the list, with the word Available next to it. Until it says that, it cannot be used.

Stage 2: Start a machine from it

On the snapshot, press Create new instance.

Pick a plan at least as large as the original. The original is a 2 GB machine, so choose 2 GB or bigger. Lightsail will not let you go smaller.

Then attach a static IP to the new instance. Without one, the address changes every time the machine restarts and your web address stops working.

You should see: the new instance turn Running after a minute or two.

That is the whole build. Connect to it and ask the three parts whether they are awake:

ssh -i ~/Downloads/your-key.pem ubuntu@NEW.IP.ADDRESS
for s in nginx mysql aiorder; do systemctl is-active $s; done
All three parts are running

Stage 3: Give it an address, and open the door

Open the doors. In the Lightsail console for the new instance, open Networking and add two rules: HTTP on port 80, and HTTPS on port 443.

Port 443 is the one everybody forgets. A brand new instance blocks it, and the symptom is confusing: the address simply spins forever and never loads.

Leave port 3306 closed. That is the catalogue, and it only ever talks to the application sitting beside it on the same machine.

Point your web address at it. In the DNS settings for your domain, add an A record: the name is your new subdomain, the value is the new static IP.

dig +short yourname.smartzees.com

You should see: the new IP address. Nothing at all, or the old address, means it has not spread yet. Wait a few minutes and run it again. Stage 4 will fail until this is right.

Stage 4: Change the name, then get the padlock

The copy still believes it is the old shop. Three files, in this order.

First, check nginx is reading the file you are about to edit. On this machine there are two files with the same name, and only one of them counts.

ls -l /etc/nginx/sites-enabled/
nginx is reading the file you edited

If there is no arrow, run these three lines once, and then the arrow will be there:

sudo rm /etc/nginx/sites-enabled/aiorder-dev
sudo ln -s /etc/nginx/sites-available/aiorder-dev /etc/nginx/sites-enabled/aiorder-dev
ls -l /etc/nginx/sites-enabled/

Now change the name.

sudo nano /etc/nginx/sites-available/aiorder-dev

Find every line starting with server_name and put your address there instead. There are two of them. Save with Ctrl+O, then Enter, then Ctrl+X.

sudo nginx -t
The front door file makes sense

Then get your own padlock. The certificate in the copy belongs to the old shop, so browsers will warn about it until you have your own.

sudo certbot --nginx -d yourname.smartzees.com --agree-tos -m you@example.com --redirect
sudo systemctl restart nginx

You should see: the word "Congratulations". If instead it complains that it cannot reach the address, stage 3 has not finished spreading. Wait, then run it again.

The restart on the second line is not a typo and it is not optional. A reload is not enough after a certificate changes: nginx keeps serving the old one until it is fully restarted.

Last, tell the application its new address.

sudo nano /var/www/ai-order/backend/.env

Change these four lines, and nothing else:

LineChange it to
FRONTEND_URLhttps://yourname.smartzees.com
PUBLIC_BASE_URLhttps://yourname.smartzees.com
DB_PASSWORDa new password of your own
ADMIN_TOKENa new one you invent

The first two are the addresses put in emailed receipts and payment return links. Left alone, your customers get sent back to the old shop after paying.

If you change DB_PASSWORD in the file, change it in the database too, or the application cannot get in:

sudo mysql -e "ALTER USER 'aiorder'@'localhost' IDENTIFIED BY 'YOUR_NEW_PASSWORD';"
sudo systemctl restart aiorder

Stage 5: Turn off the sync

What the copy brings with it

This is the one that matters more than anything else on the page.

The copy inherited a small program called aiorder-sync. Every fifteen seconds it takes new orders and writes them into the live shop's own database, the real one. On a copy that means your test orders land in front of real staff.

It starts by itself when the machine boots. Turn it off now:

sudo systemctl disable --now aiorder-sync
systemctl is-active aiorder-sync

You should see: inactive. That is the correct answer here, and the only time in this guide that inactive is good news.

Turn it back on only if this copy is meant to replace the original.

While you are here, the copy also carries the login keys of everyone who could reach the original machine. Open the list, keep your own line, delete the rest:

nano ~/.ssh/authorized_keys

Stage 6: Check it, and then look at it

Two commands on the machine:

mysql -u aiorder -p -e "SELECT COUNT(*) FROM aidata2prd_dev.items;"
The products came across
curl -sk -o /dev/null -w "shop page %{http_code}\n" https://127.0.0.1/ -H "Host: yourname.smartzees.com"
curl -sk -o /dev/null -w "health    %{http_code}\n" https://127.0.0.1/health -H "Host: yourname.smartzees.com"
The shop answers on its own machine

Both 200. The machine is happy with itself. Now go and prove it from outside, which is section 4.


4. Now open it in your browser

The machine saying 200 to itself is not the same as a customer being able to buy something. Four things to try, in this order. Each one exercises a different part of the diagram in section 2.

4.1 Open the shop

Type https://yourname.smartzees.com into your browser.

The shop as a customer sees it

What you are checking: the padlock in the address bar is closed, with no warning, and the page is your shop. A closed padlock means stage 4 worked. A page that never loads means port 443 in stage 3 was missed.

4.2 Ask it for something

Press Start Ordering and type I need milk.

Products come back, with prices

What you are checking: products come back within a few seconds, each with a picture and a price, and the counter at the top says how many matched. This one sentence proves the application, the catalogue and the chat assistant are all working, because a result cannot appear without all three.

If the page loads but nothing ever comes back, the application has stopped: sudo systemctl restart aiorder.

4.3 Put something in the basket

Press Add to cart on any product, then the basket icon at the top right.

The basket, with a total

What you are checking: the item is listed, and a subtotal, tax and total appear at the bottom. Tax being calculated means the application is doing real work, not showing you a stored page.

4.4 Try it on your phone

Open the same address on a phone, on mobile data rather than your own wifi.

What you are checking: two things at once. The shop is genuinely reachable from the outside world and not just from your desk, and it looks right on the screen most of your customers will use.


5. Everyday operations

What you wantWhat to type
Is the shop runningsystemctl status aiorder
Restart the shopsudo systemctl restart aiorder
Watch it as it workssudo journalctl -u aiorder -f
The last fifty linessudo journalctl -u aiorder -n 50
Reload the front doorsudo nginx -t && sudo systemctl reload nginx
Check the padlocksudo certbot certificates
Back up the cataloguemysqldump -u aiorder -p aidata2prd_dev > backup.sql
How full the disk isdf -h /

The padlock renews itself every ninety days, so certbot certificates is only worth running if a browser complains.


6. Changing the shop later

Two paths, and they are different because the pages folder belongs to the system while the application folder belongs to you.

The application:

rsync -az --delete backend/app/ ubuntu@HOST:/var/www/ai-order/backend/app/
ssh ubuntu@HOST 'sudo systemctl restart aiorder'

The shop pages, built on your own computer because the server has no build tools on it:

cd ai-order && npm run build:deploy
rsync -az --delete out/ ubuntu@HOST:/tmp/fe-stage/
ssh ubuntu@HOST 'sudo rsync -a --delete /tmp/fe-stage/ /var/www/ai-order/frontend-dist/ \
  && sudo chown -R www-data:www-data /var/www/ai-order/frontend-dist/'

Use build:deploy, not build. A plain build bakes in a local test address and the shop then talks to nothing.

Neither of these touches the settings file or the catalogue. That is deliberate, and it is why putting the old code back is always safe.


7. If something looks wrong

Three things go wrong, and what each looks like
What the browser showsWhat it meansWhat to do
Spins forever, never loadsPort 443 is still closedAdd the HTTPS rule, stage 3
"Not secure", or a name warningThe certificate is still the old oneStage 4, and remember restart
Page loads, no products everThe application stoppedsudo systemctl restart aiorder
Products, but no picturesPictures come from another serverNothing on this machine to fix

When none of those fit:

sudo journalctl -u aiorder -n 50

That prints the last fifty lines the application wrote about itself. The reason is usually in them, in plain English.


8. Things worth knowing

The catalogue is held in memory. All 25,701 products are loaded when the application starts, which is why a search answers in about a fifth of a second and why the first few seconds after a restart are slower than the rest.

Searches outside the catalogue cost money. When the shop has nothing matching, it asks Google. That is a paid service with a monthly allowance shared by every copy using the same key, so a busy test copy spends the original shop's allowance.

The catalogue is not backed up automatically. The mysqldump line in section 5 is the whole of it. Run it before you change anything you cannot undo.

Two things the copy inherits that are worth fixing. The database accepts connections from the internet rather than only from the machine itself, and the old spare copies of the shop pages sit in /var/www/ai-order/ taking up several gigabytes. Neither stops anything working.