Deployment guide

Krayin CRM

Overview

Krayin CRM is an open source customer relationship management application built on Laravel. One web interface covers leads moving through a configurable pipeline, persons and organizations, quotes built from a product catalogue, and an activity timeline of emails, calls, meetings and notes. It also provides web forms that capture inquiries straight into the pipeline, workflow automation, and role-based permissions.

The SecureAnyCloud image delivers the official Krayin CRM 2.2.6 release fully installed on Ubuntu 24.04 and served over HTTPS. Every per-VM secret is generated on first boot, so a working CRM is serving within minutes of launch. The image is backed by 24/7 SecureAnyCloud support.

Krayin CRM is free software published under the MIT license. Krayin is a trademark of its respective owner. SecureAnyCloud is not affiliated with, endorsed by, or sponsored by Webkul or the Krayin project. This image packages the upstream open source release, without any of the commercial add-ons sold separately upstream, together with SecureAnyCloud provisioning, hardening and support.

What you get:

  • Krayin CRM 2.2.6, served from /var/www/krayin, with the document root set to its public/ directory
  • PHP 8.3 (php8.3-fpm, over a local UNIX socket) behind Apache 2.4, reachable at https://<vm-ip>/. Port 80 only redirects to HTTPS and serves no content of its own.
  • A local MySQL 8 database, bound to 127.0.0.1 only
  • A per-VM administrator password, Laravel application key, database password and HTTPS certificate, all generated on first boot and written to a root-only file. No default, shared or published credential ships in the image. The upstream seeder of Krayin hardcodes a published administrator address and password, and in this image neither half survives the build.
  • A database that is installed and migrated at build time from the command line. The Krayin web installer (/install and its API endpoints) is blocked, so there is no setup route for a stranger to reach, even if the application were made to believe it was not installed.
  • Generated links and password reset emails that always point at the own address of this VM
  • 24/7 SecureAnyCloud support

Prerequisites

  • An active Azure subscription, an SSH key pair, and a VNet and subnet in the target region.
  • Standard_B2s (2 vCPU / 4 GiB RAM) is the recommended starting size for a small sales team. Scale up for many concurrent users or large CSV/XLSX imports.
  • NSG inbound rules: allow 22/tcp from your management network and 443/tcp (HTTPS) from wherever your team will browse. 80/tcp is optional and only redirects to HTTPS.
1

Deploy from the Azure Marketplace

Sign in to the Azure portal, choose Create a resource, search the Marketplace for Krayin CRM by SecureAnyCloud, and select Create.

On Basics, pick your subscription, resource group, region and size (Standard_B2s or larger). Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTPS (443). Then choose Review + create and Create.

2

Deploy from the Azure CLI

SecureAnyCloud images carry a Marketplace purchase plan. Accept its terms once per subscription, then create the VM and open HTTPS:

az vm image terms accept --publisher sac --offer krayin-ubuntu-24-04 --plan default
az vm create \
  --resource-group my-rg \
  --name my-krayin \
  --image sac1647283583153:krayin-ubuntu-24-04:default:latest \
  --plan-name default --plan-product krayin-ubuntu-24-04 --plan-publisher sac \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
az vm open-port --resource-group my-rg --name my-krayin --port 443 --priority 1001
3

Connect to your VM

ssh azureuser@<vm-public-ip>

First boot takes two to three minutes. It generates the administrator password, Laravel application key, database password and HTTPS certificate of this VM, and only then starts the web server. If the site does not answer immediately, first boot has not finished yet.

This order is deliberate. Apache and PHP-FPM are held closed until first boot has succeeded, so a failed first boot leaves the VM unreachable rather than serving a half-configured CRM.

4

Confirm the Krayin stack is running

sudo systemctl is-active mysql php8.3-fpm apache2 krayin-firstboot

All four report active. Now check what is listening and that the application answers:

sudo ss -lnt | grep -E ':(22|80|443|3306) ' | sort

MySQL appears only on 127.0.0.1:3306. It is never a network service on this appliance. Ports 22, 80 and 443 are the only ones reachable from outside.

curl -sk -o /dev/null -w '%{http_code}\n' https://127.0.0.1/admin/login

A 200 response confirms that Apache and PHP-FPM are serving the sign-in page. Check the installed release:

grep "const KRAYIN_VERSION" /var/www/krayin/packages/Webkul/Core/src/Core.php
5

Retrieve the first-boot credentials

Every secret on this VM was generated on its own first boot and written to a file that only root can read:

sudo cat /root/krayin-credentials.txt

The file looks like this. The real values are unique to your VM:

# sac :: Krayin CRM appliance credentials
# Generated on this VM's first boot. This file is readable only by root. # Sign in at https://<this-vm-address>/admin/login and change the password afterwards. krayin.admin.user=admin@sac.local krayin.admin.pass=<unique to this VM> krayin.db.name=krayin krayin.db.user=krayin krayin.db.pass=<unique to this VM> KRAYIN_APP_URL=https://<this-vm-address>

Confirm that only root can read the file and that the Laravel application key is the key of this VM:

sudo stat -c '%a %U:%G %n' /root/krayin-credentials.txt /var/www/krayin/.env
sudo grep -c '^APP_KEY=base64:' /var/www/krayin/.env
6

Sign in

Browse to https://<vm-public-ip>/admin/login. Your browser warns about the self-signed certificate until you install your own (Step 11). Accept the warning to continue. Sign in with the address and password from the credentials file.

Change the administrator password after you sign in. Choose Settings, then Users. The address admin@sac.local is a local address. Edit the same user to set your own email address so that password reset works.

7

Create your first lead

Krayin organizes sales work as leads moving through pipeline stages. Choose Leads in the sidebar, then Create Lead. Give the lead a title and an estimated value, and pick a Source and Type.

Under Name, choose Click to Add to attach a contact person. If you type a name that does not exist yet, Krayin offers Add as New. If the lead has no line items, remove the empty row on the Products tab before you save, because a blank product row fails validation.

Saved leads appear in the pipeline immediately, and the dashboard totals update. Open the lead to see its full record and an automatic changelog of every field that changed.

You can confirm from the shell that the data you entered persisted to the database:

sudo mysql --defaults-file=/etc/mysql/debian.cnf -D krayin -e "SELECT id, title, lead_value, created_at FROM leads ORDER BY id DESC LIMIT 5;"
8

There is no default login, and the installer is blocked

The upstream seeder of Krayin creates an administrator whose address and password are published in the source of the project. This image replaces both halves before the application is ever reachable, so that account does not exist here:

sudo mysql --defaults-file=/etc/mysql/debian.cnf -D krayin -e "SELECT id, name, email FROM users;"

Only your own administrator is listed. The web installer is refused outright, and so is the environment file:

for p in /admin/login /install /install/api/run-seeder /.env; do printf '%-26s %s\n' "$p" "$(curl -sk -o /dev/null -w '%{http_code}' https://127.0.0.1$p)"; done

/admin/login answers 200. Every installer endpoint and /.env answers 403.

A note on status codes. Krayin renders its own "404 Page Not Found" view with HTTP 200 instead of 404. For a path that is not routed, a 200 therefore does not mean the file was served, so check the body, not the status. If you put this VM behind uptime monitoring, alert on page content rather than on the status code alone.

9

How Krayin learns its address

Laravel builds absolute URLs, including password reset links and the storage disk URL, from APP_URL. On this image, krayin-baseurl.service rewrites APP_URL and the Apache ServerName from the own address of the VM on every boot. It also reissues the certificate for that address and rebuilds the configuration cache of Laravel. An Azure public IP that changes across a stop and start is therefore picked up automatically:

grep '^ServerName' /etc/apache2/conf-available/krayin-servername.conf
sudo grep '^APP_URL' /var/www/krayin/.env
openssl x509 -in /etc/ssl/krayin/krayin.crt -noout -subject -ext subjectAltName
curl -s -o /dev/null -w '%{http_code} %{redirect_url}\n' http://127.0.0.1/

Port 80 answers 301 to the HTTPS URL and serves nothing else.

10

Configure outbound email

The image ships the log mail transport. Krayin writes the messages it would have sent to storage/logs/laravel.log instead of failing against a mail server that does not exist. To point Krayin at your own SMTP relay, edit /var/www/krayin/.env:

MAIL_MAILER=smtp MAIL_HOST=smtp.your-provider.example MAIL_PORT=587 MAIL_USERNAME=your-smtp-username MAIL_PASSWORD=<set-at-first-boot> MAIL_ENCRYPTION=tls MAIL_FROM_ADDRESS=crm@your-domain.example MAIL_FROM_NAME="Your Company CRM"

Laravel caches its configuration, so rebuild the cache after any .env change:

cd /var/www/krayin && sudo -u www-data php artisan config:cache
11

Use a domain name and your own certificate

Point a DNS A record at the public IP of the VM, then pin the name so it survives reboots and IP changes:

echo "crm.your-domain.example" | sudo tee /etc/krayin/server-name
sudo /usr/local/sbin/krayin-baseurl.sh

This command writes ServerName, rewrites APP_URL to the new name and reissues a self-signed certificate for it. To replace the self-signed certificate with a trusted one, run:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d crm.your-domain.example

Certbot writes its own certificate paths into the Apache configuration. Keep /etc/krayin/server-name in place so that APP_URL continues to track the same name.

12

Inbound email and the scheduler

Krayin can turn incoming mail into leads and activities. The image ships a systemd timer, krayin-scheduler.timer, that runs the Laravel scheduler every minute. The scheduler drives the inbound-emails:process task of Krayin. Confirm that the timer is armed:

systemctl list-timers krayin-scheduler.timer --no-pager | head -3

To enable inbound capture, add your IMAP settings to /var/www/krayin/.env and rebuild the config cache as in Step 10:

IMAP_HOST=imap.your-provider.example IMAP_PORT=993 IMAP_ENCRYPTION=ssl IMAP_VALIDATE_CERT=true IMAP_USERNAME=crm@your-domain.example IMAP_PASSWORD=<set-at-first-boot>

The queue runs in sync mode, which is the upstream default, so bulk CSV and XLSX imports run inline in the web request. This is why the command-line PHP configuration leaves memory_limit uncapped while the web tier is capped at 512M. For very large imports, raise memory_limit in /etc/php/8.3/fpm/conf.d/99-krayin.ini and reload PHP-FPM.

13

Security model

  • No default credential. The published administrator address and password of Krayin never survive the build. Your administrator password, Laravel application key and database password are generated on the first boot of this VM.
  • The web installer is unreachable. Apache denies /install and every /install/api/ endpoint. This holds even if the application is made to believe it is not installed, which is the state an attacker would try to induce.
  • The environment file is not exposed. The document root is the public/ directory of Krayin, so .env sits above it. Dotfiles are also denied by name as a second line of defense.
  • Only the front controller executes. Every .php file under the document root except public/index.php is denied, so a stray or uploaded script cannot run.
  • The code tree is read-only to the web server. Only storage/ and bootstrap/cache are writable by www-data.
  • Debug mode is off and APP_ENV is production, so an error page never leaks a stack trace or configuration.
  • Nothing but SSH and HTTPS is reachable. MySQL and PHP-FPM listen on localhost only, and the X Protocol plugin of MySQL is disabled.
  • Sign-in is rate limited by Krayin itself. Five failed attempts per account per minute and twenty per address return HTTP 429.

To review what is listening and the effective SSH policy at any time, run:

sudo ss -lntu | awk '{print $1, $5}' | sort -u sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication|clientaliveinterval) '
14

Back up your CRM data

A complete backup is the database plus storage/ (uploaded files) and .env. The .env file holds the application key, and without the key, encrypted values cannot be read:

sudo mysqldump --defaults-file=/etc/mysql/debian.cnf --single-transaction --routines krayin \
  | gzip > /var/backups/krayin-$(date +%F).sql.gz
sudo tar czf /var/backups/krayin-files-$(date +%F).tar.gz \
  -C /var/www/krayin storage .env

To confirm that the dump path works without writing a file, export the schema only:

sudo mysqldump --defaults-file=/etc/mysql/debian.cnf --no-data krayin > /dev/null && echo "dump OK"

Store both archives off the VM. To restore, recreate the database, load the dump, restore storage/ and .env, and then rebuild the config cache.

15

Maintenance and upgrades

unattended-upgrades applies Ubuntu security updates automatically. Confirm that it is enabled:

grep 'Unattended-Upgrade' /etc/apt/apt.conf.d/20auto-upgrades

You upgrade Krayin itself from the upstream release archive. First read the Krayin upgrade notes for your target version and take a backup as in Step 14. Then replace the application tree, run composer install --no-dev, run php artisan migrate --force, and rebuild the caches. composer install requires the php8.3-zip extension, which this image ships.

Step 12 describes the scheduled task of Krayin and the queue. If you enable a database-backed queue instead of sync, run a queue worker.

Support

SecureAnyCloud provides 24/7 support for this image by email at sales@secureanycloud.com and live chat. Support covers deployment, retrieving the first-boot credentials, signing in, users, roles and permissions, pipelines and lead sources, outbound and inbound email, custom domains and HTTPS certificates, backups, upgrades and performance tuning.

Questions about Krayin feature behavior are answered on a best-effort basis and, where appropriate, directed to the Krayin documentation at devdocs.krayincrm.com.

Deploy on Azure

Launch Krayin CRM on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure