The installer leaves you with a running service, not with a production one. It writes a
start-up configuration — an in-memory store and two self-signed token certificates — so that the
service answers
/health/live straight away instead of refusing to start. Everything that makes it
a production instance is step 6.1. Download the archive and check it
A release carries three archives and one checksum file:
They are release assets, and the base of their address is stable —
permalink/latest always
resolves to the newest release:
permalink/latest resolves to, and the download answers 404. Take the repository address and the
current version from veriqa.app/source each time instead of keeping a
ready-made URL:
--ignore-missing is what makes this work with a single archive downloaded: the sums file lists all
three, and without the flag sha256sum fails on the two you did not take.
On Windows:
True — the archive is intact.
2. Install on Linux
The archive unpacks into a singleveriqa-authserver/ directory and carries its own installer,
install.sh. Run it as root from that directory:
veriqa (no login shell, no home directory created), copies
the program, creates the configuration and data directories, generates the token certificates,
writes the start-up configuration, installs the unit file and enables the service. It does not
start it: the start-up configuration is meant to be read before the first start, not after it.
The program directory belongs to this installation alone. Both installers write into it
without clearing it out first — a file of the archive overwrites its counterpart, anything else
stays where it is — and removal is the mirror image:
--uninstall / -Uninstall takes away the
files the installer copied and nothing else, and keeps the directory itself if something else is
still in there. Point --install-directory / -InstallDirectory at a directory of its own and the
installation comes off in one step.--urls is loopback only — the instance is reachable from the same machine and from
a reverse proxy on it, and from nowhere else.
Start the service when you have read what the installer printed:
3. Install on Windows
Unpack the.zip and run install.ps1 from the unpacked directory in an elevated PowerShell
(Windows PowerShell 5.1 and PowerShell 7 both work):
The service is registered with automatic start under the virtual account
NT SERVICE\<ServiceName> — no account and no password of your own. The configuration directory
is %ProgramData%\Veriqa; its access list is rebuilt without inheritance, so the Users group gets
no access to the secrets kept there. As on Linux, the service is registered but left stopped:
4. What the first start gives you
The installation is deliberately complete enough to start and no more:- the OpenIddict store is
InMemory— registered clients, issued tokens and the journal are lost on every restart; - the token certificates are self-signed, RSA-2048, valid for two years, and were generated on this machine;
- no channel and no OIDC client is configured, so a real sign-in cannot complete yet.
/health/ready is 200 because the start-up configuration declares no external dependency to check —
not because the instance is ready for production.
5. Where the files are
The configuration, the data-protection keys and the token certificates live outside the program directory, so that replacing the program never touches them.
On Linux
/etc/veriqa is root:veriqa 0750 and /var/lib/veriqa is 0700 owned by veriqa:
they hold secrets, and only the service account reads them.
Why the keys directory is not optional. Data-protection keys protect the sign-in cookies and
every value the host encrypts. With no keys directory and no Redis the host keeps them in memory, and
every restart invalidates what the previous process issued — users are thrown out of sign-ins that
were in flight. The installer therefore sets Veriqa:DataProtection:KeysDirectory in the environment
of the service itself, and the directory survives an update and an ordinary uninstall.
The service is registered with four environment variables — the environment is where they belong,
because they say where the configuration is read from:
The configuration directory
VERIQA_CONFIG_DIRECTORY names a directory, not a file. From it the host reads appsettings.json
and appsettings.Production.json, both optional, and layers them over the files shipped with the
program. Precedence, weakest to strongest:
appsettings.jsonof the program directory;appsettings.Production.jsonof the program directory;appsettings.jsonof the configuration directory;appsettings.Production.jsonof the configuration directory;- environment variables (
Veriqa__OpenIddict__…); - command-line arguments.
Provider = InMemory — wins over the
Provider = PostgreSQL that ships in the program directory, and why anything you pass through the
environment still wins over both.
If the variable names a directory that does not exist, the host refuses to start and says so:
VERIQA_CONFIG_DIRECTORY points to '/etc/veriqa', which does not exist. A directory that exists but
holds no files is not an error.
The self-hosted quickstart keeps the integrator’s own settings in
config/veriqa.json, resolved
against the content root. For a service the content root is the program directory, which an
update replaces — so in this delivery mode put your settings into the configuration directory
instead.6. Move to production
The installation ships a template next to the program:appsettings.Production.sample.json. It carries the same keys as the self-hosted quickstart, with
REPLACE_ME placeholders for the values. Use it as a reference and edit the configuration file
the installer wrote, rather than overwriting that file with it: the template carries no paths to the
certificates generated on this machine, and every REPLACE_ME in it is a value you still have to
supply.
/etc/veriqa: from the edit below on it holds secrets — a bot token,
connection strings, certificate passwords — and full removal neither takes it away on
Linux nor spares it on Windows, where %ProgramData%\Veriqa goes whole.
What to write there is documented once, for both delivery modes:
- stores — a relational provider and its connection string, and the audit sink: self-hosted, step 2;
- token certificates — real ones instead of the self-signed pair the installer generated: self-hosted, step 3;
- OIDC clients — self-hosted, step 4;
- channels — self-hosted, step 7, and Channel setup end to end.
SQL Server on Windows
The Windows archive does not includeMicrosoft.Data.SqlClient.SNI.dll, the native network library
the SQL Server driver uses on Windows: it is Microsoft’s, under the Microsoft Software License Terms,
and Veriqa does not redistribute it. PostgreSQL needs nothing, and neither does Linux. With
SqlServer selected for any store and the library missing, the service refuses to start, and the
message names the Microsoft.Data.SqlClient version and links its nuget.org page.
Take the library from the NuGet package Microsoft.Data.SqlClient.SNI.runtime, in the version listed
under Dependencies on that page, and put it next to the program. Downloading it, you accept
Microsoft’s terms for it:
7. HTTPS
The host speaks HTTP on the addresses of--urls / -Urls, and OpenIddict serves /connect/token
and the rest of the protocol only over https — so this step is not optional, whether or not the
instance is reachable from outside. There are two ways to put TLS in front of it.
(a) A reverse proxy on the same machine. Leave --urls at http://127.0.0.1:8080, terminate TLS
in NGINX / Caddy / IIS and forward to loopback. For OpenIddict to build https URLs the proxy must
forward X-Forwarded-Proto and X-Forwarded-For, and the proxy must be trusted — the same
ForwardedHeaders section as in
self-hosted, step 6, in the configuration
file of the installation:
appsettings.Production.json
KnownIPNetworks. The proxy is
also where per-IP rate limiting belongs — see
Production hardening.
(b) A certificate in Kestrel, with no proxy at all. This is plain ASP.NET Core configuration in
the same file (Kestrel endpoints):
appsettings.Production.json
Kestrel:Endpoints section replaces the addresses of ASPNETCORE_URLS rather than adding to
them, so no reinstall is needed — but the HTTP endpoint the installer set through --urls is gone
with it. Declare an Http endpoint alongside if you still want one (for local health probes, for
instance). Keep the server certificate readable by the service account only, next to the token
certificates.
8. Verify
https URLs; if it comes back with http, the proxy is not trusted —
step 7. The full checklist of a deployed instance, including the first sign-in, is
self-hosted, step 8.
On Linux the service log is in the journal:
Updating
An update replaces the program and keeps the configuration, the data-protection keys and the token certificates: they live outside the program directory on purpose..\install.ps1 -Uninstall from the unpacked archive of the installed
version, then .\install.ps1 from the new archive, then Start-Service Veriqa.
The second run does not overwrite an existing appsettings.Production.json and does not regenerate
existing certificates — it reports that it kept them. If you installed with non-default
--service-name, --install-directory or --config-directory, pass the same values to both runs.
--urls / -Urls has to be repeated on the installing run as well, and for a different reason: it
is not kept anywhere to be read back. The installer writes the unit file — on Windows, the
environment of the service — anew every time, so an install without it puts the service back on the
default http://127.0.0.1:8080 and the instance stops answering anything but loopback.
Removing
Ordinary removal takes away the service and the program and keeps the configuration, the data-protection keys and the certificates, so that reinstalling over them keeps current sign-ins and secrets:veriqa user:
/var/lib/veriqa goes whole, while /etc/veriqa loses the appsettings.Production.json
the installer wrote and is removed only when nothing else is left in it. On Windows all three live in
%ProgramData%\Veriqa, which goes whole.
--remove-data / -RemoveData without the uninstall switch is refused, and nothing is changed.
Removing twice is safe: with no service left, the installer says so and takes away what is left of
the installation.
Common failures
Failures that stop the host at startup — a missing certificate, an incomplete client, a channel
without a token, an unknown provider value — are the same in both delivery modes and are listed in
self-hosted, step 9. On Linux the message is in
journalctl -u veriqa.
Building the archives yourself
For the release archives the repository carries a pair of scripts that behave identically —build/publish-host.sh and build/publish-host.ps1:
linux-x64, linux-arm64 and win-x64,
pack each result together with the installer files of its OS, and leave the archives and
veriqa-authserver-<version>-SHA256SUMS.txt in artifacts/host/. The version comes from
build/Versions.props. What comes out is what this page installs — the same layout, the same
appsettings.Production.sample.json, and no appsettings.Development.json.
Next steps
Self-hosted quickstart
Stores, certificates, clients and channels — the configuration itself.
Channel setup
Telegram, WhatsApp, other channels and Email — end to end.
Configuration reference
Every section, key and default in one place.
Production hardening
What to check before shipping.