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
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.
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.
8
Edit five settings
Open the file:Near the top you will find a block that starts with What you change it to:Line by line:Save and exit:
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.environment:. Five lines in it need
your values. Everything else in the file can stay exactly as it is.What ships in the file: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.Ctrl+O, Enter, Ctrl+X.9
Start her
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.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 Apply it:
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: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
The site does not load at all
The site does not load at all
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.Sign-in fails or immediately signs me out
Sign-in fails or immediately signs me out
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:Containers restart in a loop
Containers restart in a loop
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.Everyone was signed out after a restart
Everyone was signed out after a restart
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.