The-Y CRM · Guide

The-Y CRM on your own server

One command, no config files. The installer generates all passwords itself, detects your server environment and sets everything up. You enter the license key afterwards, conveniently in the app.

What you need

→ Which server do I need? — size recommendation (small/medium/large), ports & architecture in detail.

  1. Install Docker (if not present yet)

    Check with docker version. If Docker is missing, install it with the official script:

    curl -fsSL https://get.docker.com | sh

    On servers with a panel (Plesk/cPanel/Virtualmin) Docker is often already present or one-click installable.

  2. Point the domain at the server

    At your domain provider, set an A record for your domain (e.g. crm.your-company.com) to your server's IP address. It can take a few minutes to propagate everywhere.

  3. Run the installer

    A single command on the server (as root, or with a user in the docker group):

    curl -fsSL https://the-y.at/install.sh -o install.sh && bash install.sh

    The installer only asks for domain, admin email, (optional) password and company name — then does the rest: generates all passwords, sets up the database + first admin and automatically detects whether a web server is already running on your server. Depending on that, you continue in one of the three cases below.

    Since 1.1.58 it also asks whether to set up the phone system as well — with “no” everything stays as before, and you can add it any time (phone system).

Depending on your server — one of these three cases

Case A

🟢 Fresh server

Nothing runs on port 80/443. The installer brings its own HTTPS (fetches a Let's Encrypt certificate automatically).

You don't need to do anything else — just open your domain in the browser. If the page briefly doesn't load: check DNS/ports 80+443.

Case B

🧩 Server with a panel

Virtualmin, Plesk or cPanel already occupy 80/443. The installer automatically switches to proxy mode (the app listens locally on 127.0.0.1:8090).

In the panel, add a reverse proxy / proxy pass for your domain, target:

http://127.0.0.1:8090

and enable HTTPS/Let's Encrypt for the domain in the panel. Done.

Case C

⚙️ Apache/Nginx only

You have your own web server without a panel. Here too the app runs on 127.0.0.1:8090 — add a reverse-proxy vhost (snippets below) and get a certificate with certbot.

Nginx vhost (Case C)

server {
    server_name crm.your-company.com;
    location / {
        proxy_pass http://127.0.0.1:8090;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
# then:  sudo certbot --nginx -d crm.your-company.com

Apache vhost (Case C)

<VirtualHost *:443>
    ServerName crm.your-company.com
    ProxyPreserveHost On
    ProxyPass        / http://127.0.0.1:8090/
    ProxyPassReverse / http://127.0.0.1:8090/
    RequestHeader set X-Forwarded-Proto "https"
    # SSLEngine + certificate via certbot --apache
</VirtualHost>
Important: your domain must be served over HTTPS — the login cookies are "secure" for safety. Login won't work over plain HTTP. Panels and certbot handle the certificate automatically. The only exception since 1.1.58: a server only in your own network without a domain (home network).

Final step — sign in & enter the license

  1. Open in the browser & sign in

    Go to https://your-domain and sign in with the admin email and the password the installer showed at the end.

  2. Enter the license key — in the app

    The setup wizard asks for it on first launch, or you go to Settings → License and enter your key. No config file needed. Self-hosting requires a license key — Paid (no limits) or free (the same limits as Free in the cloud: 3 users, 1,000 outgoing messages and 200 outgoing call minutes per month, 2 simultaneous calls, 2 GB, 1 brand; no support). Without a key the instance runs fully for 14 days from the first start and is read-only after that, until you enter a key. To go from free to Paid later, just enter the Paid key — your data stays.

✅ Updates & backups
Updates arrive automatically: from 1.1.53 the installation updates itself at night with update.sh – a backup is made first, the new version is checked, and if anything fails the previous version runs again. Installations from before 1.1.53 use Watchtower until you switch (about 5 minutes). A banner in the app reports new versions. You can also update yourself at any time:
cd ~/the-y-crm && bash update.sh
Without update.sh (installations from before 1.1.53): docker compose pull && docker compose up -d. The app applies database changes itself on start; there is nothing else to do after an update. For backups, regularly back up the Postgres and the MinIO volume — a simple database dump:
cd ~/the-y-crm && docker compose exec -T postgres \
  pg_dump -U crm crm | gzip > crm-backup-$(date +%F).sql.gz

Phone system

The built-in phone system (Asterisk for calls, coturn for video meetings) is optional. Everything else runs without it.

Install it right away or add it later (from 1.1.58)

install.sh asks whether to set up the phone system as well — only on Linux servers running Docker directly (not Docker Desktop, not “rootless”), because voice runs in the host network. With yes, your telephony provider’s lines, extensions, voice menus, queues, voicemail, recordings and the phone in the browser work afterwards; the CRM generates the configuration itself. With no, everything stays as before. You can add it any time, also more than once – what exists stays:

cd ~/the-y-crm && curl -fsSL https://the-y.at/install.sh -o install.sh && bash install.sh --add-phone

Ports (incoming — also in your provider’s firewall or as port forwarding on the router if the server is behind NAT): 5060/udp (SIP), 10000–20000/udp (voice), 3478/udp + 3478/tcp (STUN/TURN for video meetings), 49152–49252/udp (TURN), 443/tcp (phone in the browser, open for the app anyway). Never open from outside: 5038/tcp (AMI) and 8188/tcp (Asterisk HTTP).

# Nginx — in the HTTPS vhost of your domain, before “location /”
location = /asterisk-ws {
  proxy_pass http://172.17.0.1:8188/ws;
  proxy_http_version 1.1;
  proxy_set_header Upgrade $http_upgrade;
  proxy_set_header Connection "upgrade";
  proxy_set_header Host $host;
  proxy_read_timeout 3600s;
  proxy_send_timeout 3600s;
}
# Apache — a2enmod proxy_wstunnel; before “ProxyPass /”
ProxyPass        /asterisk-ws ws://172.17.0.1:8188/ws
ProxyPassReverse /asterisk-ws ws://172.17.0.1:8188/ws

Updates: after every update with a new worker, update.sh takes over the phone system’s base files; the running system reloads them, calls keep going. Your own parts belong in pbx/asterisk/include/. New Asterisk and coturn versions come with bash install.sh --add-phone. Check the state: bash telefonanlage.sh --pruefen.

Switching it off: docker compose rm -sf asterisk coturn, in the .env remove :docker-compose.pbx.yml from COMPOSE_FILE and set PBX=0, then docker compose up -d. The files under pbx/ stay.

Limits (1.1.58): IPv4 only; not on the standby server; WhatsApp calls and fail2ban for SIP are not preconfigured; without your own hold music the queue is silent. All items: Known Issues · in detail: SELF-HOSTING.md (German) → Telefonie. --add-phone leaves phone systems set up by hand (before 1.1.58) untouched; the section below still applies to them.

What applies from 1.1.46

If you use the built-in phone system, the following applies from version 1.1.46. The version itself arrives with the automatic updates; the parts under “Not in the image” you take over once yourself.

  asterisk:
    # … existing entries stay …
    ulimits:
      nofile:
        soft: 65536
        hard: 65536
    volumes:
      # … existing entries stay …
      - ./pbx/asterisk/modules.conf:/etc/asterisk/modules.conf:ro

Then recreate the container once, best at a quiet time (running calls drop):

docker compose up -d asterisk
Afterwards devices register again. Browser softphones do this by themselves within seconds. Desk phones and softphone apps only at their next registration interval (often 1–60 minutes); until then they cannot be reached. Restart the device or app if needed. The CRM restores “Do not disturb” by itself.

Announcements and notice before recordings: since 1.1.51 there is no computer voice any more. Each account records its announcements itself (in the browser) or uploads them as a file. Without your own recording the system plays the standard English announcement where there is one; before a recording, callers without your own notice only hear a beep (the app then shows a clear warning). More: Notice before recordings · Release notes 1.1.51 · Release notes 1.1.46 · Simultaneous calls.

Without a domain in your home network (from 1.1.58)

On a home server (e.g. CasaOS/ZimaOS, TrueNAS) without a domain and without a certificate, the CRM also works over http://<server IP>. This is meant for your own network only: the connection is not encrypted. For access from outside, use a domain with https.

With install.sh (from 1.1.59): when the installer asks for your domain, just enter the server's IP address (e.g. 192.168.1.50). The installer then writes the values below itself and tells you so.

By hand: in the .env, enter the address with http:// instead of the domain (replace the example IP), then run docker compose up -d in the installation folder:

CADDY_DOMAIN=http://192.168.1.50     # with “http://” in front, Caddy fetches no certificate
BASE_DOMAIN=192.168.1.50             # just the address, without http:// and without a path
APP_URL=http://192.168.1.50          # starts with http:// → signing in over http works, links point to this address
PUBLIC_BASE_URL=http://192.168.1.50

If an app store opens the app directly on a port (without Caddy), that address including the port goes into APP_URL, e.g. APP_URL=http://192.168.1.50:3000. The sign-in page then shows the notice that the connection in your home network is not encrypted.

Links and images in emails (from 1.1.59): the app builds links in emails and notifications (invitations, calendar file, unsubscribe and survey links, report) from APP_URL as soon as it starts with http://. So set APP_URL exactly the way you open the app in the browser (with the port, if needed). Such links only work inside your own network. The app embeds the logo and images from email templates in the email so recipients can see them.

What doesn’t work over http (browsers only allow it with https): phone in the browser and video meetings, push on your phone, adding the app to your phone, some “Copy” buttons (select and copy the text instead) and everything that needs a public https address: WhatsApp, Facebook and Instagram, Telegram, signing in with Google, connecting a Microsoft 365 mailbox. Email with IMAP/SMTP and a password works.

Interface language (from 1.1.59)

Anyone opening the app for the first time (no language chosen yet) sees it in their browser language – German, English or Turkish, otherwise German. To fix it, set it in the .env, then run docker compose up -d app in the installation folder:

DEFAULT_LOCALE=en     # de, en or tr

Order: DEFAULT_LOCALE > browser > German. The language picker in the app and the language in your own profile always come first.

“Translate” in the inbox

Without a translation service (and without your own AI or DeepL key as translator), the inbox hides the “Translate” buttons (from 1.1.59). Setting up the service: Self-hosting operations → Translation.

Stuck somewhere?

Just write to us — reply to your Founder welcome email or reach out via the-y.at. We'll help you set it up.