Guide Contents
- Before We Start: What Are We Installing?
- Part One: Preparing the Server
- Part Two: Uploading WorkUp Files
- Part Three: The Database
- Part Four: Connecting the Files to the Database
- Part Five: Domain, HTTPS, and Firewall
- Ports Summary Table
- Part Six: Setting Up Mobile Notifications (Optional)
- Part Seven: Building and Installing the Mobile App
- Troubleshooting Common Issues
Before We Start: What Are We Installing?
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.
This is what an example command looks like
Part One: Preparing the Server
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.
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.
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%.
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.
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."
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
| Extension | Exactly Why WorkUp Needs It |
|---|---|
php-mysql | Lets PHP "talk" to the MySQL database — without it, the site can't even read a single employee's name. |
php-curl | Used by WorkUp to send mobile notifications via Firebase/OneSignal, and by some internal reporting libraries. |
php-gd | Image processing (resizing, validating) when an employee photo or task attachment is uploaded, and also for generating PDF files (reports and attendance sheets). |
php-mbstring | Makes sure Arabic and English text is displayed and stored correctly without corrupting characters. |
php-zip | Used when exporting a team's attendance reports as a ZIP file containing several files at once. |
php-xml | Needed by the internal reporting/PDF libraries already included inside the project folder. |
After installing, restart Apache so it recognizes PHP:
sudo systemctl restart apache2
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.
Part Two: Uploading WorkUp Files to the Server
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
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
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).
Part Three: Importing the Database
db.sql.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.
phpMyAdmin (sudo apt install phpmyadmin -y) and upload db.sql through it, the same way you already know from XAMPP.
Part Four: Connecting the Files to the Database
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).
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.
Restart Apache to apply all the changes:
sudo systemctl restart apache2
Part Five: Domain, HTTPS, and Firewall
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
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).
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.
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.
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).
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! 🎉
Summary Table of All Ports
| Port | Use | Open 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. |
Part Six: Setting Up Mobile Notifications (Optional)
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.
Part Seven: Building and Installing the Mobile App
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.
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.
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
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.
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).
Troubleshooting Common Issues
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.logOpen 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.
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.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
mod_rewrite is enabled and AllowOverride All is actually set (step 7), then restart Apache.files folder (step 10) — it should be owned by www-data and have 775 permissions.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).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