The Complete WorkUp Installation Guide
0

Before We Start: What Are We Installing?

Think of the server as an empty "house". We're going to do four things in order: (1) We supply the house with electricity and water — this is installing the core software (Apache, PHP, and MySQL). (2) We move the furniture in — this is uploading the WorkUp files. (3) We build a "cabinet" to store all the information (employees, attendance, requests) — this is the database. (4) We give the house an address everyone knows (a domain) and a secure door (HTTPS). Only after that do we install the mobile app that "connects" to this house from anywhere.

What You Need Before Starting

1. A server device (also called a VPS) running Ubuntu 22.04 or newer. This guide is based on Ubuntu because it's the most common choice for hosting. If you don't have a server yet, you can rent one from any hosting company (Hostinger, DigitalOcean, AWS Lightsail... etc.).

2. SSH access (meaning you can "control" the server just by typing, without a screen) — you usually get this from the hosting company right after purchase (an IP address plus a password or key).

3. A complete copy of the WorkUp project folder (the same folder you're reading this from right now).

4. (Optional but recommended) A domain name such as workup.yourcompany.com. Without one, you can use the server's IP address directly, but you won't be able to enable HTTPS easily.

Every command in this guide is written inside a black box (like the one below). Copy and paste it into the terminal exactly as it is, then press Enter.
This is what an example command looks like
1

Part One: Preparing the Server

Here we install the "essential tools" any PHP site needs to work: the web server (Apache), the programming language (PHP), and the database (MySQL).
1

Connecting to the Server via SSH

Open the terminal on your machine (Terminal on Mac and Linux, or PowerShell/PuTTY on Windows) and type:

ssh root@your_server_ip

Replace your_server_ip with the number your hosting company gave you (such as 192.168.1.10). It will ask for the password — type it (it won't show as you type, that's normal) and press Enter.

SSH always uses port 22. This is the "door" you go through to control the server by typing. You don't need to memorize this number, just know that it exists and must always stay open (we'll make sure of that later, in the firewall step).
2

Updating the System

The first thing we always do on a new server is update the pre-installed software:

sudo apt update && sudo apt upgrade -y

sudo means "run this command with full administrator privileges." apt is Ubuntu's own "app store." This command makes sure everything on the server is on the latest version and more secure before we build on top of it.

3

Installing Apache (the Web Server)

Apache is the program that "receives" anyone who opens your site's link, and sends them the requested page. Without it, the server can't "talk" to browsers at all.

sudo apt install apache2 -y
sudo systemctl enable apache2
sudo systemctl start apache2

enable means "start it automatically every time the server reboots," and start means "start it right now." Apache automatically runs on port 80.

Test it now: open your browser and go to http://your_server_ip. You should see the green "Apache2 Default Page." If it appears, this step succeeded 100%.

4

Installing MySQL (the Database)

MySQL is the program where WorkUp will store everything: employee names, attendance records, requests, tasks... everything. Think of it as a "huge, organized filing cabinet."

sudo apt install mysql-server -y
sudo mysql_secure_installation

The second command will ask you several security questions (admin password, removing sample users...) — answer Y (yes) to most of them, and set a strong password for the admin (root) account and remember it well.

MySQL runs on port 3306. The important thing: this port never needs to be open to "the outside world" (the internet) — only the PHP running on the same server talks to it locally (localhost). That's why we won't open it in the firewall later, which is good for security.
5

Creating a Database and a Dedicated User for WorkUp

Log in to MySQL:

sudo mysql -u root -p

Type the password you set in the previous step. Now you're "inside" MySQL (you'll see mysql>). Copy and paste these commands one at a time (each line, then Enter):

-- Create an empty database called workup
CREATE DATABASE workup CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

-- Create a new user dedicated only to the application (not root)
CREATE USER 'workup_user'@'localhost' IDENTIFIED BY 'put_a_strong_password_here';

-- Give this user full privileges, but only on the workup database specifically
GRANT ALL PRIVILEGES ON workup.* TO 'workup_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;

Why not use root directly inside the application? Because if the connection credentials ever leak, the limited workup_user account can't touch any other database on the same server — while root can do anything. This is a security principle called "least privilege."

Write the password you chose down somewhere safe (your phone's notes app, for instance) — you'll need it shortly, in step four.
6

Installing PHP and the Extensions WorkUp Needs

PHP is the language all of WorkUp's code is written in. But PHP alone isn't enough — it needs small "extensions" to be able to do certain things (working with databases, images, ZIP files...). Install PHP and all the extensions in one go:

sudo apt install php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-zip php-xml -y
ExtensionExactly Why WorkUp Needs It
php-mysqlLets PHP "talk" to the MySQL database — without it, the site can't even read a single employee's name.
php-curlUsed by WorkUp to send mobile notifications via Firebase/OneSignal, and by some internal reporting libraries.
php-gdImage processing (resizing, validating) when an employee photo or task attachment is uploaded, and also for generating PDF files (reports and attendance sheets).
php-mbstringMakes sure Arabic and English text is displayed and stored correctly without corrupting characters.
php-zipUsed when exporting a team's attendance reports as a ZIP file containing several files at once.
php-xmlNeeded by the internal reporting/PDF libraries already included inside the project folder.

After installing, restart Apache so it recognizes PHP:

sudo systemctl restart apache2
7

Enabling mod_rewrite and FollowSymlinks

WorkUp uses "clean" links like workup.com/login instead of workup.com/auth/login.php. This requires a feature called mod_rewrite:

sudo a2enmod rewrite

Now open Apache's main configuration file:

sudo nano /etc/apache2/apache2.conf

Look for this section (with the down arrow, or Ctrl+W to search):

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

Change AllowOverride None to AllowOverride All only (leave the rest as is). Save by pressing Ctrl+O then Enter, then exit with Ctrl+X. Then restart Apache:

sudo systemctl restart apache2

Why does this matter? The .htaccess file inside the WorkUp folder explicitly requires this feature (+FollowSymlinks) and the redirect rules (RewriteRule) for the clean links. Without AllowOverride All, Apache will ignore the .htaccess file entirely and you'll get 404 errors on almost every page.

2

Part Two: Uploading WorkUp Files to the Server

Now the "house" has electricity and water. Time to move in the furniture — meaning the project files themselves.
8

Creating the Right Folder with the Right Name

This is very important: the folder must be named exactly WorkUp (same capitalization), because some internal files (404/500 error pages) reference the path /WorkUp/ directly.

sudo mkdir -p /var/www/html/WorkUp
9

Copying the Files from Your Machine to the Server

You have more than one way to do this — pick whichever is easiest for you:

Method 1 — via the scp command (directly from your machine, no extra software needed):

scp -r /path/to/WorkUp root@your_server_ip:/var/www/html/

Method 2 — FileZilla (drag and drop with a graphical interface): Download FileZilla, connect to the server via SFTP (the same SSH details: user, IP, port 22), then drag the entire WorkUp folder into /var/www/html/.

Method 3 — Git (if the project is on GitHub/GitLab):

cd /var/www/html
sudo git clone your_repo_url WorkUp
Transferring the files may take a few minutes depending on your internet speed, since the project includes some sizable ready-made libraries (PDF, text editor...). Don't worry, that's normal.
10

Setting Permissions

Now we tell the server: "Apache has read (and sometimes write) access to these files":

# Give ownership of all the files to the Apache user (www-data)
sudo chown -R www-data:www-data /var/www/html/WorkUp

# Normal read permissions for folders and files
sudo find /var/www/html/WorkUp -type d -exec chmod 755 {} \;
sudo find /var/www/html/WorkUp -type f -exec chmod 644 {} \;

# The "files" folder needs broader permissions, because the app stores
# employee photos and task attachments inside it automatically during use
sudo chmod -R 775 /var/www/html/WorkUp/files

www-data is always the name of the "user" Apache runs as on Ubuntu. The number 755 means "I can write and read, and everyone else can only read," while 775 also gives the Apache group write access, which is necessary specifically for the files folder, because the site automatically creates new folders inside it (for example, when a task attachment is uploaded).

3

Part Three: Importing the Database

We created the empty "cabinet" in Part One (step 5). Now we fill it with all the "drawers" (tables) WorkUp needs — 21 tables, ready inside a single file called db.sql.
11

Importing db.sql

mysql -u workup_user -p workup < /var/www/html/WorkUp/db.sql

Type the workup_user password you chose in step 5. This command "reads" the db.sql file line by line and executes it directly inside the workup database — within seconds, all the tables (employees, teams, attendance, tasks, requests, notifications...) will be ready and completely empty, waiting for the first user.

Prefer a graphical interface over the terminal? Install phpMyAdmin (sudo apt install phpmyadmin -y) and upload db.sql through it, the same way you already know from XAMPP.
4

Part Four: Connecting the Files to the Database

We now have "furniture" (the files) and a "cabinet" (the database) that are separate. This part connects them using just two files.
12

Editing includes/config.php

This is the only file that holds the database connection details. Open it:

sudo nano /var/www/html/WorkUp/includes/config.php

You'll find these lines near the top:

// As it is now (local default)
define("HOST","localhost");
define("USER","root");
define("PASSWORD","");
define("DATABASE","workup");

Change it to match exactly what you created in Part Three:

// After the change
define("HOST","localhost");
define("USER","workup_user");
define("PASSWORD","the_password_you_chose");
define("DATABASE","workup");

HOST stays as localhost because the database sits on the exact same server (remember: the local port 3306 from Part One). Save (Ctrl+O then Enter) and exit (Ctrl+X).

13

Editing the include_path in .htaccess

Open the main .htaccess file:

sudo nano /var/www/html/WorkUp/.htaccess

Look for this line (near the top):

php_value include_path "/Applications/XAMPP/htdocs/WorkUp/"

Change it to match the real path on this specific server (the one we created in step 8):

php_value include_path "/var/www/html/WorkUp/"

This line tells PHP: "when any code file requests a shared file, look here first." If you leave the old path (which belongs to an entirely different machine), the site will fail to load almost anything and you'll get a blank page or a 500 error.

This step is the most common cause of "the page doesn't work at all" when moving WorkUp to a new server. Double-check it carefully before continuing.

Restart Apache to apply all the changes:

sudo systemctl restart apache2
5

Part Five: Domain, HTTPS, and Firewall

The site now actually "works." All that's left is to give it an easy address people can remember (instead of an IP number), and to close every unnecessary door in the house except the ones we actually need.
14

Pointing a Domain Name at the Server

If you have a domain (like workup.yourcompany.com): first go to the domain's control panel (with the company you bought it from) and add an A record pointing to the server's IP address. Then create a site-specific configuration file:

sudo nano /etc/apache2/sites-available/workup.conf

Paste this content exactly (replace the domain with your actual domain):

<VirtualHost *:80>
    ServerName workup.yourcompany.com
    DocumentRoot /var/www/html/WorkUp

    <Directory /var/www/html/WorkUp>
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Enable this site and reload Apache:

sudo a2ensite workup.conf
sudo systemctl reload apache2
Don't have a domain yet? No problem — skip this step entirely, and open the site directly via: http://your_server_ip/WorkUp (notice the added /WorkUp at the end, since the folder is a subfolder inside Apache's public folder /var/www/html).
15

Enabling HTTPS (a Free Security Lock via Let's Encrypt)

HTTPS means all the data sent between the browser/app and the server is "encrypted" — no one on the same network (a cafe, a hotel, public Wi-Fi) can "eavesdrop" and see passwords. This step requires a real domain (from step 14):

sudo apt install certbot python3-certbot-apache -y
sudo certbot --apache -d workup.yourcompany.com

Certbot will ask you two simple questions (your email, and agreeing to the terms), then automatically does all the work itself: it issues a free security certificate, edits Apache's configuration on its own, and opens port 443. It also renews the certificate automatically every 90 days without any action needed from you.

16

Firewall — Opening Only the Right Doors

The firewall is like a "security guard" who decides which "doors" (ports) anyone from the internet is allowed to knock on. We enable it and open only what we need:

sudo ufw allow OpenSSH
sudo ufw allow 'Apache Full'
sudo ufw enable

OpenSSH keeps port 22 open — never skip this line, or you'll lock the door on yourself and permanently lose the ability to access the server remotely! 'Apache Full' opens ports 80 and 443 together, in one go.

Make sure the sudo ufw allow OpenSSH command succeeds before typing sudo ufw enable. If you enable the firewall without this line, your current SSH session will be cut off and you won't be able to connect to the server again except directly through the hosting company's control panel (Console/VNC).
17

Final Test

Open your browser and go to your site's address (https://workup.yourcompany.com or http://your_server_ip/WorkUp). WorkUp's login page should appear — if it does, you've successfully completed the hardest part! 🎉

6

Summary Table of All Ports

A "port" is simply a number that identifies "which door" on the server is used for a particular type of connection. This is a summary of every port mentioned exactly in this guide.
PortUseOpen to the Internet?Why
22 SSH — remote command-line control of the server Yes You (the admin) need it to log in and run commands from anywhere. We kept it open with the first command in the firewall step.
80 HTTP — regular (unencrypted) site browsing Yes This is the default port for any browser or mobile app when you type http://. Apache listens on it automatically as soon as it's installed.
443 HTTPS — encrypted, secure browsing Yes Used when you type https://. Enabled automatically when an SSL certificate is installed via Certbot (step 15). Strongly recommended for actual production use.
3306 MySQL — communicating with the database No Used only by the PHP code running on the same server (a local/localhost connection). There is never any need to open it to the internet, and leaving it closed is more secure.
7

Part Six: Setting Up Mobile Notifications (Optional)

This step is optional, but required if you want employees to receive actual notifications on their phones (a new request, a task, an approval...). WorkUp supports two providers — choose only one.
18

Firebase or OneSignal — Which Should You Choose?

Firebase Cloud Messaging (FCM): A free service from Google, requires a Firebase project (from console.firebase.google.com) and a "Server Key" from the project settings.

OneSignal: An independent notification service, slightly easier for initial setup, requires an App ID and a REST API key from onesignal.com.

After obtaining the keys (whichever service you chose), go to the admin control panel abma, then Settings, and enter the keys in the designated fields. WorkUp saves them and starts using them immediately, with no need to restart anything.

8

Part Seven: Building and Installing the Mobile App

Last step: we build the installation file (APK) for the employee app, put it on the phone, and connect it to the server we set up above.
19

What You Need on Your Computer (Not the Server)

This part is done on the computer (Windows/Mac/Linux) you're working on, not on the server. You'll need:

1. Flutter SDK — download it from flutter.dev and follow the installation instructions for your OS.

2. Android Studio — provides the Android SDK needed to build an Android app (even if you won't use the Android Studio interface itself).

3. A real Android phone (connected via USB cable) or an Emulator from Android Studio.

After installing, make sure everything's fine by typing:

flutter doctor

This command checks your machine and shows a checkmark (✓) or an error (✗) for each requirement. Make sure everything is green before continuing.

20

Downloading the Project's Libraries (pub get)

Open the terminal inside the main mobile app folder (named new_app):

cd new_app
flutter pub get

This command reads the pubspec.yaml file and automatically downloads all the "ready-made components" the app depends on (camera, qibla-compass maps, notifications...) — exactly like downloading ready-made Lego pieces instead of building them from scratch.

21

Building the Installation File (APK)

flutter build apk --release

This command turns all the Dart code into a single file that can be installed on any Android phone. It may take several minutes the first time. The resulting file will be exactly here:

new_app/build/app/outputs/flutter-apk/app-release.apk
22

Transferring the File to the Phone and Installing It

Method 1 (Easiest): If the phone is connected to the computer via USB with "Developer Options" and "USB Debugging" enabled, type:

flutter install

Method 2: Upload the app-release.apk file to Google Drive or send it to yourself via WhatsApp/email, and download it directly on the phone.

Either way, the first time you install an app from outside the Google Play Store, the phone will ask you to enable an option called "Install unknown apps" — approve it only for this specific app.

23

First Launch: Connecting the App to the Server

The first time you open the app, a screen will ask for the "server address." You have two options:

Scan a QR code: If you've prepared a QR code containing your server's link (plain text, or JSON with a backend_url key), scan it directly with the app's camera.

Manual entry: Type your server's full address including http:// or https://, such as:

https://workup.yourcompany.com

The app saves this address internally and won't ask you for it again. After that, log in with a real employee account that exists in the database (create one first from the abma panel if it doesn't exist yet).

9

Troubleshooting Common Issues

If you run into a problem, the solution is probably here. Look for the description closest to what you're seeing.
⚠️ I'm getting an "Internal Server Error 500" page
Most common cause: the include_path in .htaccess (step 13) doesn't match the real location of the files. Check the error log to find out exactly why:
sudo tail -f /var/log/apache2/error.log
Open the site in a new browser while this command is running, and watch the last line that appears — it will tell you the exact file and line.
⚠️ A completely blank page, no message at all
This usually means a PHP error is being hidden by the "don't display errors" setting. To temporarily enable displaying them (for diagnosis only — turn it off again afterward), open includes/config.php and remove the comment (/* */) around the first two lines at the top, then reload the page to see the actual error message.
⚠️ "Cannot connect to the database"
Make sure the details in includes/config.php (user, password, database name) exactly match what you created in step 5, and confirm the MySQL service is actually running:
sudo systemctl status mysql
⚠️ Every link (without .php) gives a 404, even the login page
Make sure mod_rewrite is enabled and AllowOverride All is actually set (step 7), then restart Apache.
⚠️ Can't upload an employee photo or task attachment
Check the permissions and owner of the files folder (step 10) — it should be owned by www-data and have 775 permissions.
⚠️ The mobile app says "Unable to connect to the server"
Make sure the address entered in the app is correct and complete (starts with http:// or https://, with no trailing slash at the end), that the firewall allows the port being used (80 or 443), and that the phone can actually reach the server's address (try opening the same link from the phone's browser first).
⚠️ Lost the SSH connection to the server after enabling the firewall
This only happens if you forgot sudo ufw allow OpenSSH before enable (step 16). The fix: access the server directly through the hosting company's control panel (usually an option called Console or VNC), then run:
sudo ufw allow OpenSSH
sudo ufw reload
Made with care for the WorkUp team — keep this file as a permanent reference, and feel free to read it more than once.
Installation WorkUp