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#
./scripts/deploy.sh setup-ssl lawn.example.comThe 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#
Step 1: Point the domain at the server
In your DNS, the A record for
lawn.example.commust 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.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.
Step 3: Check that it will renew
bashcertbot renew --dry-runThe 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#
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.
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.
Step 3: Copy the files to the names nginx reads
bashcp /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 nginxStep 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#
./scripts/deploy.sh add-domain lawn yourdirectory.comThis 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
wwwseparately 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:
rm /etc/nginx/sites-enabled/directorylab-lawn-yourdirectory.com.conf
nginx -t && systemctl reload nginxMore sites on the same server#
Run add-site again with a new name:
./scripts/deploy.sh add-site plumbers| Part | What the new site gets |
|---|---|
| Address | plumbers.example.com. Add its DNS record and certificate as for the first. |
| Port | One above the highest in use: 5002, then 5003. |
| Database | Its own, directorylab_plumbers, in the same PostgreSQL container. |
| Memory | Its 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. |
| Settings | Its 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.
docker build -t directorylab /opt/directorylab
./scripts/deploy.sh update-site lawn
./scripts/deploy.sh update-site plumbersChange a setting on one site or all of them#
./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=3set-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_KEYthis way on a site that is in use.
Remove a site#
./scripts/deploy.sh backup lawn
./scripts/deploy.sh remove-site lawnThe 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:
sed -i 's/client_max_body_size 12M;/client_max_body_size 64M;/' /etc/nginx/sites-enabled/directorylab-lawn*.conf
nginx -t && systemctl reload nginxFor 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).
Stuck on a step? Send a message.