In this Guide, I want to cover installing ZITADEL with PostgreSQL on a Linux system. Please be aware that PostgreSQL support is still in Beta at the time of this writing, and you will need a PostgreSQL installation with Version 14 or higher.

NGINX Proxy

Create a new subdomain and point it to your server. Use certbot -d domain.name for creating a new SSL Cert. Create a new file in /etc/nginx/sites-available/domainname

server {
    server_name domain.com;

    listen 443 ssl;

    ssl_certificate     /etc/letsencrypt/live/domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location / {
        grpc_pass grpc://localhost:8080;
        grpc_set_header Host $host:$server_port;
    }
}

PostgreSQL

We need a database for the software. This can be created by the following commands:

sudo -u postgres psql
postgres=# create database zitadel;
postgres=# create user zitadel with encrypted password 'mypass';
postgres=# grant all privileges on database zitadel to zitadel;

Config File

I often create directories for software in /opt/projectname. Then a config.yaml file could look like this:

ExternalSecure: true
ExternalDomain: 'domain.name'
ExternalPort: 443

Database:
    postgres:
        Host: localhost
        Port: 5432
        Database: zitadel
        MaxOpenConns: 25
        MaxConnLifetime: 1h
        MaxConnIdleTime: 5m
        Options:
        User:
            Username: zitadel
            Password: zitadel
            SSL:
                Mode: disable
                RootCert:
                Cert:
                Key:
        Admin:
            Username: postgres
            Password: postgres
            SSL:
                Mode: disable
                RootCert:
                Cert:
                Key:

We should also create an init.yaml file like this:

FirstInstance:
    Org:
        Human:
        # use the loginname root@zitadel.localhost
        Username: 'root'
        Password: 'RootPassword1!'

Installation

Use the following command to download and install Zitadel:

LATEST=$(curl -i https://github.com/zitadel/zitadel/releases/latest | grep location: | cut -d '/' -f 8 | tr -d '\r'); wget -qO-  https://github.com/zitadel/zitadel/releases/download/$LATEST/zitadel_Linux_$(uname -m).tar.gz  | tar -xz zitadel && sudo mv zitadel /usr/local/bin

Masterkey

We should generate and save an masterkey:

echo "$(tr -dc A-Za-z0-9 </dev/urandom | head -c 32)"

Start

For the first run:

zitadel start-from-init \
    --config /opt/zitadel/config.yaml \
    --steps /opt/zitadel/init.yaml \
    --masterkey "${ZITADEL_MASTERKEY}" \
    --tlsMode external

Now visit https://domain.name/ui/console and you can log in.

If your custom username and password don’t work, then try out the default account:

  • username: root@zitadel.localhost or zitadel-admin
  • password: RootPassword1!

After that, you can start it with:

zitadel start \
    --config /opt/zitadel/config.yaml \
    --masterkey "${ZITADEL_MASTERKEY}" \
    --tlsMode external

Systemd Daemon

I also set up a custom systemd daemon. For that, create a new file in /etc/systemd/system:

[Unit]
Description=Custom Zitadel
After=postgresql.service

[Service]
RestartSec=2s
Type=simple
User=zitadel
WorkingDirectory=/opt/zitadel
ExecStart=/usr/local/bin/zitadel start --config /opt/zitadel/config.ya
ml --masterkey YOUR_MASTERKEY --tlsMode external
Environment=USER=zitadel HOME=/opt/zitadel
ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure

[Install]
WantedBy=multi-user.target

Summary

That was it. Surprisingly easy. The ZITADEL team is also really fast responding to problems. I had some issues with the beta software, and all of these issues were fixed after a few days.

This post was even mentioned by their company account: