Skip to main content
From an empty virtual machine to PostQueen running on your own domain, over HTTPS. No prior server experience is needed. Every command is written out, and every value you need to change is shown before and after. Set aside about thirty minutes, most of it waiting for downloads.
Want to look around first without renting anything? Try her locally runs the same software on your own machine in five minutes.

What you need

Three things, and the guide helps you get all of them.

Step by step

1

Create the server

Order a virtual machine running Ubuntu 24.04. When it is ready your provider gives you a public IP address that looks like 203.0.113.42, and either a password or an SSH key.Write the IP address down. You need it in the next two steps.
2

Point your domain at it

In whichever service manages your domain, add an A record:That gives you postqueen.example.com. Throughout the rest of this guide, replace postqueen.example.com with whatever you actually chose.DNS changes take a few minutes to spread. You can check from your own machine:
That prints your server’s IP address. Do this now, because the certificate step later will fail if the name does not resolve yet.
3

Connect to the server

Use your own IP address. If your provider gave you a different username, such as ubuntu, use that instead. The first time you connect it asks whether you trust the host; answer yes.Everything from here runs on the server, not on your own machine.
4

Install Docker

Docker’s own install script handles this in one go:
Confirm it worked:
Both print a version number. If either answers “command not found”, the script did not finish, and running it again is safe.
5

Close the doors you are not using

Only web traffic and your own SSH session should be able to reach this machine.
Allow OpenSSH before enabling the firewall. If you enable it first you will lock yourself out of your own server and have to recover through your provider’s console.
Port 4007 is not on that list, and should not be. PostQueen listens on 4007 locally, and the reverse proxy you set up later is the only thing that talks to her. The outside world only ever sees 443.
6

Download PostQueen

Stay in this folder for the rest of the guide. It holds docker-compose.yaml, which is the single file that describes the whole install, along with the dynamicconfig folder that the scheduler reads at startup.
7

Generate a signing key

This one value protects every login session. Generate a random one and keep the output:
It prints a long line of letters and numbers. Copy it somewhere safe, you need it in the next step.
Set this once and never change it casually. Changing it later signs everyone out, and because it is also the fallback key for encrypting stored channel credentials, changing it can disconnect every channel you have connected. If you want to be able to rotate it later, set ENCRYPTION_KEY to its own separate value now, and see Configuration Reference.
8

Edit five settings

Open the file:
nano is a plain text editor that runs in the terminal. Arrow keys move around, typing edits. When you are finished, press Ctrl+O then Enter to save, and Ctrl+X to quit.
Near the top you will find a block that starts with environment:. Five lines in it need your values. Everything else in the file can stay exactly as it is.What ships in the file:
What you change it to:
Line by line:
No trailing slashes. https://postqueen.example.com/ with a slash on the end will be reported as a configuration issue in the log and can break sign-in. Leave the slash off.
Why /api? Everything reaches her through one address. Inside the container a small proxy sends anything starting with /api to the backend and everything else to the web interface. So the browser is told the backend lives at yourdomain/api, and there is no second port or second hostname to set up.
Leave BACKEND_INTERNAL_URL as http://localhost:3000. That one is not about your domain at all, it is how the web interface talks to the backend inside the same container, and pointing it at your public address will break things.
Save and exit: Ctrl+O, Enter, Ctrl+X.
9

Start her

First run downloads several gigabytes of images, so give it a few minutes. When it finishes you will see each container reported as started or healthy.Watch her come up:
You are waiting for:
Press Ctrl+C to stop watching.
Read the lines just after that one. She checks her own configuration at the end of startup and prints anything suspicious as Configuration issue. She does not refuse to start when something is wrong, so a running container is not by itself proof that the settings are right. If you see those warnings, fix them now rather than wondering later why sign-in fails.
Check she is answering locally before you put a proxy in front of her:
An HTTP/1.1 200 OK means she is up.
10

Add your domain and HTTPS

She is running, but only on the server itself. The last piece is a reverse proxy, which accepts HTTPS on port 443, gets a certificate for your domain automatically, and passes requests to port 4007.Domain and HTTPS explains what that means and why she needs it. If you want the short version, Caddy does the whole job in three lines: Caddy.Come back here when https://postqueen.example.com loads in your browser.
11

Create your account and close the door

Open https://postqueen.example.com and sign up. The first account is yours and owns the install.Then stop anyone else from signing up. Open docker-compose.yaml again and change:
Apply it:
Changed settings only take effect after docker compose down followed by up. A plain restart reuses the old container with the old values, which is a common source of “I changed it and nothing happened”.
Existing accounts, including yours, can still sign in normally. This only closes new sign-ups. You can still invite teammates from inside the app.
She is live on your domain, over HTTPS, and closed to strangers.

If something is not right

Work outwards. curl -I http://localhost:4007 on the server tells you whether she is up at all. If that works but the domain does not, the problem is the reverse proxy or DNS, not PostQueen. Check that dig +short postqueen.example.com returns your server’s IP.
Almost always a URL mismatch. FRONTEND_URL has to be character for character the address in your browser’s bar, including https:// and with no trailing slash. She builds her allowed-origin list from it, so a mismatch means the browser is refused. Search the log for it:
Every network builds its return address from FRONTEND_URL, so if that value is wrong or was changed after you registered the app, the redirect will not match what the network has on file. OAuth connect errors covers the specific messages.
Usually memory. Check with docker stats, and docker compose logs postqueen for the reason it died. The Temporal stack alone wants around 1 GB, so 2 GB total leaves very little headroom.
JWT_SECRET changed. It signs every session, so a new value invalidates all of them. Set it once and keep it. Self-host troubleshooting has more.

Next steps

Worth doing soon rather than eventually.

Set up email

Without it, password resets quietly do nothing. This is the most common regret.

Back up your data

Which volumes hold data you cannot rebuild, and how to restore one

Connect your channels

Each network needs its own app keys, created by you

Sort out media storage

Local disk is fine to start with. Know the tradeoff before you grow.