ITFlow 26.11.3
Overview
ITFlow is an open-source platform for managed service providers and IT teams. One web application keeps each client's documentation: contacts, locations, assets, networks, software and licences, domains, certificates, documents and a credential vault. It also runs the service desk (tickets, recurring tickets, time tracking and SLAs) and handles quotes, invoices, recurring invoices, payments and expenses. Your clients get a portal where they raise and follow their own requests.
This guide covers launching and using the SecureAnyCloud ITFlow 26.11.3 on Ubuntu 24.04 AMI on Amazon EC2. It is one version of the SecureAnyCloud help desk, IT service and project management listing on AWS Marketplace. You choose it as the software version when you subscribe and launch.
What you get:
- No setup wizard and no default login. Upstream ITFlow is set up in a browser wizard that asks for database details and creates the first user. On this image, the wizard is never reachable (
/setup/answers 404). First boot runs ITFlow's own setup code once. It creates the database, the first company and an administrator with a password unique to your instance, then closes setup. - Nothing baked into the image. The image ships an empty MariaDB data directory, no
config.phpand an empty/var/lib/itflow. Every instance creates its own database, installation id, backup encryption key and vault key on first boot. - No database password at all. ITFlow runs as its own system user,
itflow. MariaDB accepts that user only over the local socket, from processes running asitflow(unix_socketauthentication). MariaDB has no network listener. - HTTPS from the first boot. nginx serves ITFlow on port 443 with a certificate generated on your instance. Port 80 redirects to HTTPS, and requests for a host name the instance does not serve get no answer. ITFlow's HTTPS-only mode is on, so its session cookies are
SecureandHttpOnly. - Only ITFlow's pages run PHP. nginx runs a PHP file only when the address names a real ITFlow page. The configuration, setup, the cron script, the function and include files, the bundled libraries, the form handler fragments and any trick address (
/login.php/x, doubled or encoded slashes) answer 404. - Read-only code. The ITFlow code is owned by root and read-only to PHP.
config.phpis owned by root and readable only by ITFlow. Nothing on the web can change the application or its settings file. - Uploaded files are never run. Files that you and your clients upload are served with a sandboxing content security policy and
nosniff, never as PHP. Backups and temporary files are never served at all. - Abuse limits and cross-site protection. Sign-in requests are rate-limited per client address, on top of ITFlow's own lockout. ITFlow's form and ajax handlers and sign-out refuse requests opened from other sites. ITFlow sees the real client address and the configured host name, never values a client sends in headers.
- Metadata access blocked. nginx, PHP-FPM, MariaDB, ITFlow's cron and first boot are blocked from the instance metadata service. A mail server, webhook or integration address pointed at it gets nothing back. The AMI requires IMDSv2.
- Cron as a service. ITFlow's scheduled jobs (mail, recurring tickets and invoices, reminders, cleanup) run every minute from
itflow-cron.serviceas theitflowuser, with no crontab. - Fully patched Ubuntu 24.04 LTS at build time, with unattended security upgrades switched on.
- Image contents: ITFlow 26.11.3 (the upstream source of commit
e07fbf6d1fef, checksum verified), nginx, PHP 8.3 FPM, MariaDB 10.11, Ubuntu 24.04 LTS, cloud-init and the AWS Systems Manager agent. - Defaults: the default SSH user is
ubuntu, the architecture is x86_64 and the recommended instance type is m5.large. - 24/7 SecureAnyCloud support
Prerequisites
- An AWS account subscribed to the listing, an EC2 key pair and a VPC subnet with a route to the internet (or a private route that you use for management).
- A security group that allows TCP 22 (SSH) from your admin network. It must also allow TCP 443 (ITFlow) and TCP 80 (redirects to HTTPS) from the networks where your technicians and clients work.
- ITFlow holds your clients' documentation and credentials, so keep ports 80 and 443 as narrow as you can.
Launch the instance
In the AWS Marketplace listing, choose Continue to Subscribe, then Continue to Configuration. Pick ITFlow 26.11.3 on Ubuntu 24.04 as the software version, choose your Region, then choose Launch through EC2.
Choose m5.large (or larger for many technicians), your key pair and a security group as described in Prerequisites.
To launch with the AWS CLI instead, replace the values in angle brackets:
aws ec2 run-instances --region <region> --image-id <ami-id-from-the-listing> \
--instance-type m5.large --key-name <your-key-pair> \
--security-group-ids <your-security-group> --subnet-id <your-subnet> \
--metadata-options HttpTokens=required,HttpEndpoint=enabled \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=itflow}]'First boot builds the database. It takes about two minutes after the instance is running.
Connect to your instance
Connect over SSH as the ubuntu user, which is the SSH user for ITFlow 26.11.3 on Ubuntu 24.04:
ssh -i <your-key.pem> ubuntu@<public-ip>Check the services
First boot creates the database, sets the password and mints the certificate. nginx and ITFlow's cron start only after first boot has finished:
systemctl is-active nginx php8.3-fpm mariadb itflow-cron
sudo test -f /var/lib/sac/data/itflow-firstboot.done && echo FIRSTBOOT_DONEAll four services are active and the first boot marker is present:
active active active active FIRSTBOOT_DONEOnly SSH and nginx listen on network ports. MariaDB has no network listener, and PHP-FPM uses a local socket:
sudo ss -lntp | awk 'NR>1 && $4 !~ /^127\.0\.0\.5[34]/ {split($6, p, "\""); print $4, p[2]}' | sort0.0.0.0:22 sshd 0.0.0.0:443 nginx 0.0.0.0:80 nginx [::]:22 sshd [::]:443 nginx [::]:80 nginxGet your URL and password
sudo cat /root/itflow-credentials.txtThe file is readable by root only:
# ITFlow 26.11.3 - generated on first boot by itflow-firstboot.service
# These credentials are unique to this instance; none was baked into the image. Keep this file secret. ITFLOW_URL=https://ec2-<public-ip-dashed>.compute-1.amazonaws.com/ ITFLOW_ADMIN_EMAIL=admin@localhost.localdomain ITFLOW_ADMIN_PASSWORD=<ITFLOW_ADMIN_PASSWORD>
#
# Open ITFLOW_URL in a browser (self-signed certificate minted on this instance's first boot; port 80 redirects to # https) and sign in with the e-mail address and password above; ITFlow's Get started page opens. Then, under your
# name (top right > Account), set your own e-mail address (Profile) and change the password (Security; this re-wraps
# ITFlow's vault key). Backup encryption key: Administration > Maintenance > Backup shows it (also in # /etc/itflow/config.php) - keep a copy away from # this server; a backup cannot be restored without it. # MariaDB: unix socket only (no TCP listener); ITFlow signs in as the OS user itflow (no database password). # root signs in over the socket:
sudo mysql itflow
# Configuration: /etc/itflow/config.php (root-owned, read-only to ITFlow). Files: /var/lib/itflow/uploads
# Cron:
systemctl status itflow-cron (runs cron/cron.php every minute as itflow; Administration > Maintenance > Cron)
# Change the name it serves as:
sudo itflow-set-hostname <your-dns-name>
# User guide: https://secureanycloud.com/stacks/itflow-26-11-3/The URL uses the instance's public DNS name from the EC2 instance metadata. The certificate also names the public and private IP addresses, and nginx answers only to the names in the certificate.
The name is fixed at first boot. If you stop and start the instance without an Elastic IP and its public address changes, run sudo itflow-set-hostname with the new name (Step 8). Better still, give the instance an Elastic IP or your own DNS name.
Sign in and make the account yours
Open the ITFLOW_URL in your browser. The certificate is self-signed, so your browser asks you to confirm it the first time. You can install your own certificate instead (Step 8).
Sign in with the email address admin@localhost.localdomain and the password from Step 4.
The first time the administrator signs in, ITFlow opens its Get started page. It has eight steps: Cron, Email, Backups, Billing, Support, Team, Content and First client. You can do each one now, skip it, or leave it for later. Cron is already ticked, because the image runs ITFlow's cron for you.
Then open your account (your name at the top right, then Account) and complete these tasks:
- On Profile, change the email address to your own. ITFlow signs you in with it and sends notifications to it.
- On Security, change the password. Do it there, inside ITFlow, not in the database. ITFlow encrypts the credential vault with a key wrapped by your password, and changing the password re-wraps that key. ITFlow then signs you out, and you sign in again with the new password.
- On Security, turn on multi-factor authentication.
Until every Get started step is done or skipped, the dashboard shows a Finish setting up bar to continue from.
Add a separate ITFlow user for each technician (Administration, Users) instead of sharing the administrator account. Tickets, clients, assets, documentation, invoices and the rest are in the menu on the left.
Mail, cron and outbound connections
ITFlow sends ticket and invoice email and can turn incoming email into tickets. Set your SMTP and IMAP servers in the Get started Email step, or in Administration, Mail. Until you do, ITFlow sends no mail.
ITFlow's scheduled jobs run from itflow-cron.service, which runs ITFlow's cron dispatcher every minute as the itflow user. ITFlow shows each job's last run and result under Administration, Maintenance, Cron.
Check the service:
systemctl status itflow-cron --no-pager | head -5ITFlow connects out only to servers that an administrator configures. These are your mail servers, Stripe if you take card payments, an AI provider if you turn one on, and your identity provider if you set up single sign-on. Nothing is contacted on its own.
ITFlow's one-click updater runs git from inside PHP, and this image does not let PHP start programs. New ITFlow releases arrive as new versions of this listing.
ITFlow keeps an encryption key for the credential vault in a cookie named user_encryption_session_key. ITFlow sets it Secure and HttpOnly with SameSite=None. The session cookie PHPSESSID is Secure, HttpOnly and SameSite=Lax. nginx refuses cross-site requests to ITFlow's form handlers regardless.
Backups and the backup encryption key
ITFlow generates a backup encryption key for your instance on first boot. It protects the backups that ITFlow makes from Administration, Maintenance, Backup. A backup cannot be restored without the key. Copy the key from that page into your password manager, away from this server.
Your data lives in three places:
- Everything you enter is in the MariaDB database
itflow(/var/lib/mysql). - Uploaded files are under
/var/lib/itflow/uploads. - The configuration (database name, base URL, installation id and backup key) is
/etc/itflow/config.php.
All three are on the root volume, so the simplest backup is an EBS snapshot of it. For a consistent copy while ITFlow is running, run:
sudo mariadb-dump --single-transaction --routines itflow | gzip > <backup-dir>/itflow-$(date +%F).sql.gz
sudo tar -C / -czf <backup-dir>/itflow-files-$(date +%F).tar.gz var/lib/itflow/uploads etc/itflowThe dump holds every password hash and the encrypted vault, so store it as carefully as the instance.
To give ITFlow more room, enlarge the root volume in the EC2 console (Volumes, Modify). Ubuntu grows the file system on the next boot.
To keep ITFlow's data on its own EBS volume instead, attach a volume and stop ITFlow. Copy /var/lib/mysql and /var/lib/itflow onto the new volume. Mount it back over the same paths with bind mounts in /etc/fstab before you start the services again. Contact support if you would like help with the move.
Your own DNS name and certificate
Point a DNS record at the instance. An Elastic IP keeps the address stable.
Then set the name that ITFlow is served as. This command mints a new self-signed certificate for the name and points nginx and ITFlow's base URL (used in every emailed link) at it. It also updates the URL in /root/itflow-credentials.txt and keeps the name across reboots:
sudo itflow-set-hostname <your-domain>To use a certificate from a public or internal certificate authority instead, copy it over the generated pair and reload nginx. An example is a certificate issued by Let's Encrypt for <your-domain>. Running itflow-set-hostname again replaces it with a self-signed certificate:
sudo install -m 0644 <your-domain>.crt /etc/nginx/ssl/itflow.crt
sudo install -m 0600 <your-domain>.key /etc/nginx/ssl/itflow.key
sudo nginx -t && sudo systemctl reload nginxSecurity checks
nginx serves only ITFlow's pages and static files. Setup, the configuration, the cron script, the function files, the bundled libraries and trick addresses answer 404. Plain HTTP redirects to HTTPS, and a request for a name the instance does not serve gets no answer at all:
H=$(sudo grep '^ITFLOW_URL=' /root/itflow-credentials.txt | cut -d= -f2- | sed -E 's#https://([^/]+)/#\1#') for p in /login.php /config.php /setup/ /cron/cron.php /functions.php /includes/check_login.php /login.php/x //config.php /libs/vendor/autoload.php /.git/config; do curl -sk -o /dev/null -w "%{http_code} $p\n" --resolve "$H:443:127.0.0.1" "https://$H$p" done curl -s -o /dev/null -w 'http:// -> %{http_code}\n' --resolve "$H:80:127.0.0.1" "http://$H/" curl -sk -o /dev/null -w 'unknown host name -> %{http_code}\n' --resolve "other.example:443:127.0.0.1" "https://other.example/" || true200 /login.php 404 /config.php 404 /setup/ 404 /cron/cron.php 404 /functions.php 404 /includes/check_login.php 404 /login.php/x 404 //config.php 404 /libs/vendor/autoload.php 404 /.git/config http:// -> 301 unknown host name -> 000Every service runs with the instance metadata service blocked:
for u in nginx php8.3-fpm mariadb itflow-cron; do echo "$u $(systemctl show -p IPAddressDeny --value $u)"; donenginx 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 php8.3-fpm 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 mariadb 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32 itflow-cron 168.63.129.16/32 fd00:ec2::254/128 169.254.169.254/32The code is owned by root, and PHP runs as itflow:
stat -c '%U:%G %a %n' /var/www/itflow /var/www/itflow/login.php /etc/itflow
sudo stat -c '%U:%G %a %n' /etc/itflow/config.phproot:root 755 /var/www/itflow root:root 644 /var/www/itflow/login.php root:itflow 750 /etc/itflow root:itflow 640 /etc/itflow/config.phpMaintenance
Operating system security updates install automatically. Run sudo apt-get update && sudo apt-get upgrade to apply everything else.
nginx, PHP-FPM and MariaDB restart cleanly, and ITFlow keeps all of its data. New ITFlow releases arrive as new versions of this listing, and support can help you move your data to one.
These are the locations of the main components:
- ITFlow: /var/www/itflow (owned by root, read-only to PHP)
- Configuration: /etc/itflow/config.php (root:itflow, mode 0640)
- Database: MariaDB database itflow (/var/lib/mysql)
- Uploaded files, sessions and backups: /var/lib/itflow
- nginx site: /etc/nginx/sites-available/sac-itflow
- Certificate and key: /etc/nginx/ssl/itflow.crt, /etc/nginx/ssl/itflow.key
- Cron: itflow-cron.service
- Helper: /usr/local/sbin/itflow-set-hostname
- Credentials: /root/itflow-credentials.txt (mode 0600)
- Source and changes: /usr/share/doc/itflow/SOURCE.txt
Security recommendations
- Allow port 22 from your admin network only. Allow ports 80 and 443 only from the networks where your technicians and clients work.
- Use your own DNS name and a certificate that your users' browsers trust (Step 8).
- Change the administrator email address and password as soon as you sign in, turn on multi-factor authentication, and give each technician their own user (Step 5).
- Keep a copy of the backup encryption key away from the server (Step 7).
- Keep the operating system patched, and snapshot the root volume regularly.
Support and licensing
ITFlow is open source under the GNU Affero General Public License version 3, by the ITFlow project and its contributors. There is no per-user or per-client licence fee.
The image ships ITFlow exactly as released, with its bundled PHP and JavaScript libraries. /usr/share/doc/itflow/SOURCE.txt names the commit it came from and lists every file the image leaves out or adds. No source file is modified.
The AMI price covers SecureAnyCloud's hardening, first-boot setup and support.
- Email: sales@secureanycloud.com
- Website: https://secureanycloud.com
- Support: 24/7, with a 24 hour response SLA
All product and company names are trademarks or registered trademarks of their respective holders. Use of them does not imply any affiliation with or endorsement by them.
Deploy on AWS
Launch ITFlow 26.11.3 on Ubuntu 24.04 on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com