Skip to contentLaunch price30% off every kit for the first 250 buyers155 left
DirectoryLab

Loading the guides…

Local LabGuides
Go live

More sites, domains and HTTPS

Give a site a real certificate and a domain of its own, run several sites on one server, then change or remove them.

Updated 7 Oct 2026 · written for Local Lab 1.2.1

On this page

A site made with add-site answers at <name>.<BASE_DOMAIN> with a temporary certificate that browsers do not trust. This guide gives it a real certificate, puts it on a domain of its own and adds more sites to the same server. Every command is run as root in /opt/directorylab, and the examples carry on from Deploy to a server: a site called lawn at lawn.example.com.

Get a real certificate#

bash
./scripts/deploy.sh setup-ssl lawn.example.com

The script asks you to choose:

  • 1) Cloudflare Origin Certificate: for a domain whose DNS is at Cloudflare with the proxy switched on. You paste in a certificate that Cloudflare gives you.

  • 2) Let's Encrypt: for anything else. The certificate is fetched for you.

With Let's Encrypt#

  1. Step 1: Point the domain at the server

    In your DNS, the A record for lawn.example.com must hold the server's IP address, and port 80 must be reachable from the internet. If the DNS is at Cloudflare, set the record to DNS only.

  2. Step 2: Run setup-ssl and answer 2

    The script runs certbot, which proves you control the domain, fetches the certificate and rewrites that domain's nginx file to use it.

  3. Step 3: Check that it will renew

    bash
    certbot renew --dry-run

    The kit schedules no renewal of its own. certbot's own timer does it, and this command tests that it can.

certbot registers the certificate under the address admin@<BASE_DOMAIN>. That is one more reason to set BASE_DOMAIN to a domain of yours.

With a Cloudflare origin certificate#

  1. Step 1: Create the certificate in Cloudflare

    In the Cloudflare dashboard, go to SSL/TLS, then Origin Server. Create a certificate there. It must list every address this site answers on. Cloudflare shows a certificate and a private key. Keep the page open: the key is shown once.

  2. Step 2: Run setup-ssl and answer 1

    Paste the certificate, press Enter, then press Ctrl and D. Paste the private key, press Enter, then press Ctrl and D.

  3. Step 3: Copy the files to the names nginx reads

    bash
    cp /etc/ssl/directorylab/lawn.example.com.pem /etc/ssl/directorylab/lawn.pem
    cp /etc/ssl/directorylab/lawn.example.com.key /etc/ssl/directorylab/lawn.key
    chmod 600 /etc/ssl/directorylab/lawn.key
    nginx -t && systemctl reload nginx
  4. Step 4: Finish in Cloudflare

    Switch the proxy on for the DNS record, and set the SSL/TLS encryption mode to Full (strict).

A site has one certificate file, and every domain you add to that site reads the same one. So with this option, one origin certificate has to cover all of the site's addresses.

Use your own domain#

bash
./scripts/deploy.sh add-domain lawn yourdirectory.com

This writes a second nginx file, /etc/nginx/sites-enabled/directorylab-lawn-yourdirectory.com.conf, that sends the new domain to the same site. Then:

  • Point the domain at the server with an A record, as before.

  • Give it a certificate: ./scripts/deploy.sh setup-ssl yourdirectory.com.

  • Add www separately if you want it. Each command adds one address: ./scripts/deploy.sh add-domain lawn www.yourdirectory.com, with its own DNS record and certificate.

  • Change Website Address (Base URL) in Site Settings, on the General tab, to the address you want in emails.

The first address goes on working, and nothing sends visitors from one address to another: the site answers on all of them.

There is no command to take a domain away. Delete its file and reload nginx:

bash
rm /etc/nginx/sites-enabled/directorylab-lawn-yourdirectory.com.conf
nginx -t && systemctl reload nginx

More sites on the same server#

Run add-site again with a new name:

bash
./scripts/deploy.sh add-site plumbers
PartWhat the new site gets
Addressplumbers.example.com. Add its DNS record and certificate as for the first.
PortOne above the highest in use: 5002, then 5003.
DatabaseIts own, directorylab_plumbers, in the same PostgreSQL container.
MemoryIts own limit of 768 MB. The script's notes reckon three sites and the database fit in 4 GB. Watch real use with ./scripts/deploy.sh status.
SettingsIts own sites/plumbers/.env with its own SECRET_KEY, its own uploads folder, its own setup wizard and admin account.

What the sites share is the code. All of them run from one image, so an update covers every site at once. A template file you change is part of that image: the change reaches no site until the image is rebuilt, and then it reaches all of them.

After changing a template
docker build -t directorylab /opt/directorylab
./scripts/deploy.sh update-site lawn
./scripts/deploy.sh update-site plumbers

Change a setting on one site or all of them#

bash
./scripts/deploy.sh set-env lawn RECAPTCHA_SITE_KEY=your-site-key RECAPTCHA_SECRET_KEY=your-secret-key
./scripts/deploy.sh set-env all GUNICORN_WORKERS=3

set-env takes a site name, or all for every site, then one or more KEY=VALUE pairs. A key that is already in the site's .env has its line replaced. A new key is added at the end.

  • Nothing changes until the site restarts: ./scripts/deploy.sh update-site lawn.

  • A value with &, | or \ in it is written wrongly when it replaces an existing line. Edit the file by hand for those.

  • Never set SECRET_KEY this way on a site that is in use.

Remove a site#

bash
./scripts/deploy.sh backup lawn
./scripts/deploy.sh remove-site lawn

The first line keeps a last copy of the database. remove-site stops the container and deletes directorylab-lawn.conf. Then it asks two questions: whether to drop the database, and whether to delete the site's files.

The upload limit#

nginx refuses any upload over 12 MB before it reaches Local Lab, which itself accepts files up to 64 MB. A larger CSV file gets the error "413 Request Entity Too Large". To raise the limit for a site and its extra domains:

bash
sed -i 's/client_max_body_size 12M;/client_max_body_size 64M;/' /etc/nginx/sites-enabled/directorylab-lawn*.conf
nginx -t && systemctl reload nginx

For sites you add later, change the same line in nginx/site.conf.template first.

nginx also waits no more than 120 seconds for a page. A long import can end with a timeout page in the browser. Open Listings to see what was saved, then import the same file again with Skip Duplicates ticked.

The browser still warns about the certificate after I pasted one in

The pasted files are saved under the domain's name and nginx reads the site's name. Run the copy step.

setup-ssl says "SSL cert already exists"

It found a file from an earlier paste and stopped. To paste again, delete /etc/ssl/directorylab/lawn.example.com.pem and .key first.

Cloudflare shows a redirect loop, or error 526

A loop means the encryption mode is Flexible: Cloudflare asks the server over http, and nginx sends every http request to https. Error 526 means the mode is Full (strict) while the server still has the temporary certificate. Install the origin certificate and use Full (strict).

Can two sites share one database?

No. Each add-site makes a database of its own, and each site has its own listings, users and settings.

Stuck on a step? Send a message.