Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deployment

What you’ll need

  • A valid domain (e.g. taskminder.de)
  • A server (minimum 2GB RAM and 20GB storage) running Ubuntu (≥ 24.04 LTS) with sudo or root access
  • The codebase of TaskMinder from https://github.com/TaskMinder/TaskMinder

1. DNS Configuration

Before proceeding with the server setup, configure your domain to point to your Ubuntu server.

Get Your Server’s Public IP Address

On your server, run:

curl ifconfig.me

Copy the returned IP (e.g., 203.0.113.42). Make sure the server is not behind a router. The following guide will use this example IP — replace it with your actual IP.


Configure DNS Records

Go to your domain registrar’s DNS management page (e.g., Namecheap, GoDaddy, Cloudflare etc.) and add the following records:

TypeNameValue (replace)TTL
A@203.0.113.42Automatic / 3600
Awww203.0.113.42Automatic / 3600

This assumes you’re using example.com and want www.example.com to also work.

We also use a subdomain for monitoring (monitoring.example.com) and a subdomain for a status page.

We use https://betterstack.com/ as it offers custom subdomains for the status page, but you may choose another provider. After setting up the status page, follow BetterStack’s instructions to configure the CNAME record.

For the monitoring page (monitoring.example.com), add the following record:

TypeNameValue (replace)
Amonitoring203.0.113.42

Wait for Propagation

DNS propagation can take a few minutes to several hours. Use tools like:

Once your domain resolves to your server’s IP, proceed to the next step.


2. Install Required Packages

Update and install dependencies:

This installs (if not already installed) Git, curl, NGINX, libnginx-mod-http-lua (for Lua in NGINX), lua-cjson (for NGINX), UFW, and Fail2Ban:

sudo apt update && sudo apt upgrade -y
sudo apt install -y git curl nginx ufw fail2ban libnginx-mod-http-lua lua-cjson

Verify lua was installed and is enabled:

See if the module was auto-enabled, if not, enable it first before proceeding:

ls /etc/nginx/modules-enabled/ | grep lua

Install Docker and Docker Compose:

Follow the official Docker documentation to install Docker and Docker Compose:

🔗 https://docs.docker.com/engine/install/ubuntu/

Enable and start Docker

sudo systemctl enable docker
sudo systemctl start docker

Enable and configure firewall (UFW)

sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
sudo ufw enable

Configure Fail2Ban

sudo systemctl enable fail2ban
sudo systemctl start fail2ban

Check status:

sudo fail2ban-client status

3. Clone the Project from GitHub

cd /opt
sudo git clone https://github.com/TaskMinder/TaskMinder.git
cd TaskMinder

4. Configure NGINX

First, modify the nginx.config file to replace taskminder.de with your actual domain name.

vi nginx.config
# or
nano nginx.config

Install Certbot and Obtain SSL Certificates

Install Certbot and its NGINX plugin:

sudo apt install -y certbot python3-certbot-nginx

Run Certbot to obtain SSL certificates (replace example.com and subdomains with your actual domains):

sudo certbot -d example.com -d www.example.com -d monitoring.example.com

Certbot will automatically update the configuration file at /etc/nginx/sites-available/default. Delete this file, as you’ll be using your custom config instead. Also, delete the symlink: sudo rm /etc/nginx/sites-enabled/default

Now that you know the location and filenames of the generated certificates, update your original nginx.config at /opt/TaskMinder/nginx.config. Replace the certificate paths with the correct ones provided by Certbot.

Add Gzip and Lua settings in general nginx.config

Open the main nginx configuration file:

sudo nano /etc/nginx/nginx.conf

Inside the http { } block, comment out all related gzip lines, as we will be using it for compression work. Furthermore, add this line in the http block:

##
# Lua Maintenance Flag Setting
##
lua_shared_dict maintenance_flag 1m;

Deploy Your Final NGINX Configuration

# Copy your updated configuration
sudo cp /opt/TaskMinder/nginx.config /etc/nginx/sites-available/taskminder

# Enable and test the configuration
sudo ln -s /etc/nginx/sites-available/taskminder /etc/nginx/sites-enabled/
sudo nginx -t

# Restart NGINX to apply changes
sudo systemctl restart nginx

5. Set Up Non-Root User

Running as root means a compromised container could gain full system access. It is highly recommended to run the server as a non-root user (least privilege). We’ll use the name ubuntu for this guide, but you may choose another name.

sudo adduser ubuntu
sudo usermod -aG sudo ubuntu
sudo usermod -aG docker ubuntu

If adduser fails, the user likely already exists (common on cloud providers like AWS or DigitalOcean). In that case, just add them to the docker group:

sudo usermod -aG docker ubuntu

Give the user access to the project folder:

sudo chown -R ubuntu:ubuntu /opt/TaskMinder

Log out and reconnect as the ubuntu user:

exit
ssh ubuntu@<your-ip-address>

For enhanced security, use SSH key-based authentication instead of password-based logins to reduce the risk of unauthorized access. After adding your SSH key and verifying the connection, disable both root logins and password authentication:

Edit and/or uncomment the following lines in /etc/ssh/sshd_config:

PermitRootLogin no
PasswordAuthentication no

Then restart SSH:

sudo systemctl restart ssh

6. Automated Backup Setup (via Cron)

Make the Backup Script Executable

The cron service needs permission to run the script. You only need to do this once.

chmod +x /opt/TaskMinder/backup-cmds/db_backup.sh

Add the Job to Crontab

This will schedule the script to run automatically.

Open the crontab editor for the current user:

   crontab -e

Add the following line to the bottom of the file, then save and exit:

   0 * * * * /opt/TaskMinder/backup-cmds/db_backup.sh >> /var/log/backup.log 2>&1

Verify the Setup

Confirm the job was added successfully by listing the active cron jobs:

   crontab -l

You should see the line you just added.


7. Add Docker Secrets and .env.production

Navigate back to the TaskMinder folder and create directories for secrets and backups:

cd /opt/TaskMinder
mkdir docker_secrets
mkdir db-backups

Before starting the application, create the following text files inside the docker_secrets/ folder. These files are used as Docker secrets for configuration:

FilenameDescription
db_name.txtName of the PostgreSQL database.
db_password.txtPassword for the PostgreSQL database user.
db_host.txtHost for the database, usually postgres when running in docker.
db_user.txtPostgreSQL database username.
redis_port.txtRedis port (default is 6379).
session_secret.txtSecure session secret (e.g., generate one with openssl rand -base64 32).
database_url.txtProvides the database URL for Prisma ORM: postgresql://db_user:db_password@taskminder-postgres:5432/db_name
encryption_key.txtEncryption key for server-side encryption in the database, generated with openssl rand -base64 32
encryption_key_secondary.txtRotation key for server-side encryption, generated with openssl rand -base64 32
encryption_key_lookup.txtLookup key for hashes for server-side encryption, generated with openssl rand -base64 32
proxy_hop.txtProxy hop count for additional reverse proxies that are configured by the server provider. Add 1 to account for the NGINX config.

8. Run Docker Compose and reset git changes

Navigate to the project root and build/start the containers:

cd /opt/TaskMinder
docker compose up -d --build

Reset git changes:

git reset --hard

And build/start the containers again:

docker compose up -d --build

9. TaskMinder Deployment Complete

Your TaskMinder server should now be running at:


10. What’s Next?

  • Create an account to set up a class and add your subjects, teams, and timetable.
  • Visit https://monitoring.example.com to change the default password “admin” to a secure one. You’ll be prompted to do this upon your first login.

11. Subsequent Updates

This guide covers minor version upgrades. For major version upgrades, please refer to the relevant migration guides to check for any breaking changes. Before upgrading, enable maintenance mode by adding a file flag with:

touch /etc/nginx/maintenance.flag
  1. Navigate to the root folder of the project and stop the Docker Compose process:

    docker compose down
    
  2. Pull the latest changes from the main branch on GitHub:

    git pull origin main
    
  3. Rebuild and restart the Docker containers:

    docker compose up -d --build
    
  4. Disable maintenance mode:

    rm /etc/nginx/maintenance.flag