COMFAST WiFi Router Initial Setup
This guide covers the initial configuration of a COMFAST WiFi router via its web interface.
Prerequisites
- A LAN cable to connect the COMFAST router to your PC
- Access to a web browser
Steps
- Connect a LAN cable between the COMFAST router and your PC.
- Configure your network adapter so the gateway is set to
192.168.0.1 (the router default IP).
- Alternatively, connect to the COMFAST wireless network directly.
- Open a browser and navigate to
http://192.168.0.1.
- Log in with the router credentials when prompted.
Notes
- Use credentials provided on the router label or set by your administrator. Change the default password after first login.
Convert Dynamic Disks to Basic Disks Non-Destructively
Microsoft's official method to convert dynamic disks back to basic disks requires backing up data, formatting, and restoring. This guide covers a non-destructive alternative using TestDisk.
Option 1: Use TestDisk (Recommended for unbootable systems)
- Boot from a live environment or attach the disk as secondary to a working machine.
- Download and run TestDisk (free, open-source).
- Follow the prompts to analyse and repair the partition table.
Option 2: Microsoft workaround (for bootable systems)
- Open Disk Management (
diskmgmt.msc).
- Follow the WORKAROUND section of the relevant Microsoft KB article to revert without data loss.
Option 3: Import a foreign dynamic disk
- Connect the disk to another Windows PC. Open Disk Management.
- The disk shows as Foreign. Right-click and select Import Foreign Disk.
Notes
- Errors such as INTERNAL Error C10000B6 during import indicate TestDisk is the recommended recovery path.
- Always back up data before attempting disk conversion.
Back Up Google Drive Files from Linux
This guide explains how to back up Google Drive files from Linux using the drive CLI tool with cron for automated scheduling.
Steps
- Install the
drive CLI tool:
go get -u github.com/odeke-em/drive/cmd/drive
- Initialise drive for your Google account:
mkdir ~/gdrive-backup
cd ~/gdrive-backup
drive init
Follow the OAuth prompt to authorise access.
- Pull your Drive files locally:
drive pull
- Optionally configure an exports directory in
.driverc:
# File: .driverc
exports-dir=/home/your_user/gdrive-exports
- Exclude exported documents from sync in
.driveignore:
# File: .driveignore
_exports$
- Automate with a cron job (daily at 2 AM):
0 2 * * * cd ~/gdrive-backup && drive pull
Notes
- rclone is an alternative that may be easier to install:
sudo apt-get install rclone then rclone config.
Fix: apt-get install msodbcsql Fails with "ODBC Driver Already Detected"
When installing Microsoft ODBC drivers on Linux, you may get Installation Failed, ODBC Driver 11 (or 13) for SQL Server Detected! A previous install left registry entries that conflict.
Steps
- Remove conflicting ODBC packages:
sudo apt-get remove unixodbc mssql-tools odbcinst libodbc1
- Remove stale ODBC configuration files:
sudo rm /etc/odbcinst.ini
sudo rm /usr/local/etc/odbcinst.ini
- Fix broken package dependencies:
sudo apt-get -f install
- Install the ODBC driver directly:
sudo dpkg -i msodbcsql_13.1.4.0-1_amd64.deb
- Reinstall supporting packages:
sudo apt-get install unixodbc mssql-tools libodbc1
Alternative
odbcinst -u -d -n "ODBC Driver 13 for SQL Server"
Notes
- The package filename can be found in
/var/cache/apt/archives/ after a failed install attempt.
Install and Configure Etherpad
Etherpad is a real-time collaborative editor. This guide covers resetting broken plugins via MySQL and running Etherpad behind an Apache reverse proxy.
Reset Plugins via MySQL
mysql -u root etherpad
DELETE FROM plugin_hook;
DELETE FROM plugin;
MySQL Configuration Example
In settings.json:
"dbType" : "mysql",
"dbSettings" : {
"user" : "etherpad",
"host" : "127.0.0.1",
"port" : "3306",
"password": "your_db_password",
"database": "etherpad"
}
Apache Reverse Proxy
<VirtualHost pad.example.com:80>
DocumentRoot /usr/local/www/pad
ServerName pad.example.com
RewriteEngine On
RewriteRule ^/(.*)$ http://127.0.0.1:9000/$1 [proxy]
</VirtualHost>
Notes
- Replace
your_db_password with a strong password.
- Etherpad listens on port 9000 by default.
Remove Orphaned Disk UUIDs from VirtualBox
When you delete a virtual hard disk file manually without removing it through VirtualBox first, the UUID entry remains in VirtualBox configuration. This guide shows how to purge stale entries.
Steps
- List all registered virtual disks:
VBoxManage list hdds
- Remove a stale entry:
VBoxManage closemedium disk <uuid-or-path> --delete
- Verify the entry is gone:
VBoxManage list hdds
Notes
- The
--delete flag removes both the UUID entry and the underlying file. Omit it to only deregister without deleting the file.
Install macOS High Sierra in VirtualBox on Windows 10
This guide walks through installing macOS High Sierra in VirtualBox on Windows 10 using a pre-built VMDK image and custom VBoxManage commands.
Prerequisites
- 64-bit Windows 10 PC with at least 4 GB RAM and a dual-core processor
- Virtualisation enabled in BIOS
- VirtualBox 5.2+ installed
- macOS High Sierra VMDK image file
Steps
- Extract the image: Right-click the
.rar file and select Extract here.
- Create a new VM: Name it
macOS 10.13 High Sierra, Type Mac OS X, Version macOS 10.13, 3-6 GB RAM, use the extracted VMDK as disk.
- Adjust VM Settings: Enable EFI, set chipset to PIIX3 or ICH9, 2 CPU cores with PAE/NX, 128 MB video memory.
- Close VirtualBox before running VBoxManage commands.
- Apply VBoxManage patches via Administrator Command Prompt (replace "Your VM Name"):
cd "C:\Program Files\Oracle\VirtualBox"
VBoxManage.exe modifyvm "Your VM Name" --cpuidset 00000001 000106e5 00100800 0098e3fd bfebfbff
VBoxManage setextradata "Your VM Name" "VBoxInternal/Devices/efi/0/Config/DmiSystemProduct" "iMac11,3"
VBoxManage setextradata "Your VM Name" "VBoxInternal/Devices/efi/0/Config/DmiSystemVersion" "1.0"
VBoxManage setextradata "Your VM Name" "VBoxInternal/Devices/efi/0/Config/DmiBoardProduct" "Iloveapple"
VBoxManage setextradata "Your VM Name" "VBoxInternal/Devices/smc/0/Config/DeviceKey" "ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"
VBoxManage setextradata "Your VM Name" "VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC" 1
- Start the VM and follow the macOS installer.
VirtualBox Networking Modes Explained
VirtualBox provides multiple networking modes for VM adapters, each controlling how the VM communicates with the host, other VMs, and the internet.
Networking Modes
- Not Attached: Network card present but no connection. Useful for testing disconnection scenarios.
- NAT: VM accesses the internet through the host. Not reachable from outside without port forwarding.
- NAT Network: Like NAT but allows multiple VMs on the same network to communicate with each other.
- Bridged: VM connects directly to the host physical NIC, appearing as a separate machine on the LAN.
- Internal: Private network visible only to selected VMs, not to the host or internet.
- Host-Only: Network between host and VMs only. No internet access by default.
- Generic: Flexible mode with custom drivers. Includes UDP Tunnel and VDE sub-modes.
Quick Reference
Mode | VM-Host | VM-VM | VM to Internet | VM from Internet
-------------|---------|-------|----------------|-----------------
Host-Only | Yes | Yes | No | No
Internal | No | Yes | No | No
Bridged | Yes | Yes | Yes | Yes
NAT | No | No | Yes | Port fwd only
NAT Network | No | Yes | Yes | Port fwd only
Connect to PostgreSQL on AWS RDS Through a Bastion Host
AWS RDS instances are typically not publicly accessible. This guide shows how to connect through a bastion host using PuTTY SSH tunneling.
Prerequisites
- PuTTY and PuTTYgen installed on Windows
- Your EC2 key pair
.pem file
- Bastion host address and RDS endpoint
- pgAdmin 4 installed
Steps
- Open PuTTYgen, load your
.pem file, and save it as a .ppk private key.
- In PuTTY Session: enter the bastion host address, port 22, SSH.
- In Connection > SSH > Auth: browse to your
.ppk file.
- In Connection > SSH > Tunnels: Source port
5432, Destination rds-endpoint:5432, click Add.
- Save and open the session to connect to the bastion host.
- In pgAdmin 4: create a new server with host
127.0.0.1, port 5432, and your RDS credentials.
Notes
- The SSH tunnel must remain open while using pgAdmin.
Configure Office 365 DNS Records on DigitalOcean
This guide covers adding the required DNS records in DigitalOcean to get Office 365 email services working.
Steps
- Domain verification TXT record: Add a TXT record with name
yourdomain.com. (trailing dot) and the value provided by Microsoft. Wait up to 60 minutes for propagation.
- MX record: Use the hostname and priority from Microsoft's setup wizard.
- SPF TXT record: Name
yourdomain.com. or @, value "v=spf1 include:spf.protection.outlook.com -all"
- CNAME records (e.g. autodiscover): Name
autodiscover.yourdomain.com., value as provided by Microsoft (with trailing dot).
- SRV records for Lync/Teams:
Name: _sip._tls.yourdomain.com.
Hostname: sipdir.online.lync.com.
Priority: 100 | Weight: 1 | Port: 443
Name: _sipfederationtls._tcp.yourdomain.com.
Hostname: sipfed.online.lync.com.
Priority: 100 | Weight: 1 | Port: 5061
Notes
- Always include trailing dots on fully-qualified domain names in DigitalOcean DNS.
- The SPF record must be the only SPF record for the domain.
Enable "Ignore Permission Errors" in WinSCP
WinSCP can be configured to silently ignore SFTP permission errors encountered during file transfers.
Steps
- Open WinSCP and edit a session.
- Click Advanced to open Advanced Site Settings.
- Navigate to SFTP in the left panel.
- Check Ignore permission errors.
- Click OK and save the session.
Notes
- This suppresses "Permission denied" errors when WinSCP reads file ownership metadata it has no access to.
- The option is per-session and must be set for each saved site individually.
Install OSRM and Nominatim on Ubuntu 16.04
OSRM (Open Source Routing Machine) provides routing APIs. Nominatim provides geocoding from OpenStreetMap data. This guide covers installing both on Ubuntu 16.04.
Install OSRM
sudo apt-get update && sudo apt-get upgrade
sudo apt-get install unattended-upgrades
mkdir osrm && cd osrm && mkdir data && cd data
wget -O map.osm.pbf https://download.geofabrik.de/your-region.osm.pbf
sudo apt install build-essential git cmake pkg-config \
libbz2-dev libstxxl-dev libstxxl1v5 libxml2-dev \
libzip-dev libboost-all-dev lua5.2 liblua5.2-dev libluabind-dev libtbb-dev
cd ..
git clone https://github.com/Project-OSRM/osrm-backend.git
cd osrm-backend && mkdir build && cd build
cmake .. && sudo make install
cd ../..
osrm-extract data/map.osm.pbf -p osrm-backend/profiles/car.lua
osrm-contract data/map.osrm
osrm-routed data/map.osrm
Verify OSRM
curl "http://127.0.0.1:5000/route/v1/driving/LONG1,LAT1;LONG2,LAT2?steps=true"
Install Nominatim
sudo apt-get install -y build-essential cmake g++ libboost-dev \
libexpat1-dev zlib1g-dev libxml2-dev libbz2-dev libpq-dev \
libgeos-dev libgeos++-dev libproj-dev \
postgresql-server-dev-9.5 postgresql-9.5-postgis-2.2 postgresql-contrib-9.5 \
apache2 php php-pgsql libapache2-mod-php php-pear php-db git
git clone --recursive git://github.com/twain47/Nominatim.git
cd Nominatim && mkdir build && cd build
cmake .. && make
sudo -su postgres
./utils/setup.php --osm-file ../../data/map.osm.pbf --all 2>&1 | tee setup.log
exit
sudo service apache2 restart
Verify Nominatim
curl "http://127.0.0.1/reverse.php?format=json&lat=YOUR_LAT&lon=YOUR_LON&zoom=18"
Fix Easy Digital Downloads Upload Limit
If EDD file uploads fail due to size limits, increase PHP and WordPress upload settings.
Steps
- In
php.ini:
upload_max_filesize = 256M
post_max_size = 256M
memory_limit = 256M
max_execution_time = 300
Restart Apache: sudo service apache2 restart
- In
wp-config.php (before the final comment line):
@ini_set('upload_max_size', '256M');
@ini_set('post_max_size', '256M');
@ini_set('memory_limit', '256M');
- In
.htaccess (Apache only):
php_value upload_max_filesize 256M
php_value post_max_size 256M
Verify
In WordPress admin, go to Media > Add New and check the maximum upload size shown.
HTML Special Character Entity Reference
HTML special characters must be escaped using entity codes to avoid being interpreted as markup.
Common Entities
Character | Named Entity | Numeric Entity
-----------------|--------------|---------------
' (apostrophe) | ' | '
" (quote) | " | "
& (ampersand) | & | &
< (less-than) | < | <
> (greater-than)| > | >
Notes
' is valid in HTML5 but not HTML4 — use ' for maximum compatibility.
Install Equella (OpenEquella) on Ubuntu
Equella (now OpenEquella) is a digital repository platform. This guide covers installing build dependencies, compiling from source, and running the installer on Ubuntu.
Steps
- Install dependencies:
apt-get update && apt-get upgrade
apt install git imagemagick libav-tools
- Install Java 8:
add-apt-repository ppa:webupd8team/java
apt-get update && apt-get install oracle-java8-installer
- Install sbt:
echo "deb https://dl.bintray.com/sbt/debian /" | sudo tee -a /etc/apt/sources.list.d/sbt.list
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823
apt-get update && apt-get install sbt
- Install Yarn and Node.js:
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn
curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
sudo apt-get install -y nodejs
- Install MySQL:
apt install mysql-server && mysql_secure_installation
- Clone and build:
cd /var/www
git clone https://github.com/equella/Equella.git
cd Equella && sbt installerZip
- Run the installer:
cd /var/www
unzip Equella/Installer/target/equella-installer-*.zip
cd equella-installer-*/
apt-get install libxrender1 libxtst6 libxi6
java -jar enterprise-install.jar
Notes
- Generate a Java keystore before running the installer:
keytool -genkey -alias server -keyalg RSA -keysize 2048 -keystore keystore.jks
Install Sylius E-Commerce on Ubuntu with Apache and PHP 7.2
Sylius is a PHP e-commerce framework built on Symfony. This guide covers installing it on Ubuntu with Apache, PHP 7.2, MySQL, and Composer.
Steps
- Install Apache and PHP 7.2:
apt-get update && apt-get upgrade
apt-get install apache2 software-properties-common
add-apt-repository -y ppa:ondrej/php && apt-get update
apt-get install php7.2 php7.2-cli php7.2-common zip
apt-get install php7.2-curl php7.2-gd php7.2-json php7.2-mbstring php7.2-intl php7.2-mysql php7.2-xml php7.2-zip
- Set your timezone in
php.ini for both apache2 and cli.
- Install Composer:
curl -sS https://getcomposer.org/installer -o composer-setup.php
php composer-setup.php --install-dir=/usr/local/bin --filename=composer
- Install MySQL:
apt-get install mysql-server && mysql_secure_installation
- Create the Sylius project:
cd /var/www/html
composer create-project sylius/sylius-standard acme
cd acme/
- Configure the database in
.env.local:
DATABASE_URL=mysql://your_username:your_password@127.0.0.1/sylius_db
- Set ownership, configure Apache DocumentRoot to
public/, then restart:
chown -R www-data: .
service apache2 restart
- Install front-end dependencies:
apt install nodejs npm
sudo apt remove cmdtest
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
apt-get update && apt-get install yarn
npm install && npm install gulp-cli -g && npm install gulp -D
yarn install && yarn build
- Enable Apache modules:
a2enmod rewrite headers expires
service apache2 restart
chown -R www-data: public/
Fix Missing /var/run/sshd Directory After Reboot
On Ubuntu containers (e.g. under Proxmox LXC), the /var/run/sshd directory may not be recreated after a reboot, causing SSH to fail with Missing privilege separation directory: /var/run/sshd.
Fix Option 1: systemd-tmpfiles (Preferred)
echo "d /var/run/sshd 0755 root root -" | sudo tee /etc/tmpfiles.d/sshd.conf
sudo systemd-tmpfiles --create
Fix Option 2: rc.local
Add to /etc/rc.local before the exit 0 line:
mkdir -p /var/run/sshd
chmod 0755 /var/run/sshd
Verify
sudo systemctl restart ssh
sudo systemctl status ssh
Remove index.php from Nextcloud URLs
By default, Nextcloud includes index.php in URLs. Enable clean URLs by activating Apache mod_rewrite and updating the Nextcloud configuration.
Steps
- Check if
mod_rewrite is enabled:
apachectl -M | grep rewrite
- Enable it if not:
a2enmod rewrite
a2enmod env
service apache2 restart
- Fix .htaccess ownership:
chown www-data:www-data /var/www/nextcloud/.htaccess
- Add to
/var/www/nextcloud/config/config.php (inside the $CONFIG array):
'htaccess.RewriteBase' => '/',
- Regenerate .htaccess:
sudo -u www-data php /var/www/nextcloud/occ maintenance:update:htaccess
- Restart Apache:
systemctl restart apache2
Install Cocorico Marketplace on Ubuntu
Cocorico is an open-source marketplace platform built with Symfony. This guide covers installing it on Ubuntu with Apache, PHP 7.1, MongoDB, MySQL, and SSL.
Steps
- Install prerequisites and Certbot:
apt-get update && apt-get upgrade
apt-get install -y zip nano curl git apache2 software-properties-common
add-apt-repository universe
add-apt-repository -y ppa:certbot/certbot
apt-get update && apt-get -y install certbot python-certbot-apache
- Enable Apache modules, set AllowOverride All in
/etc/apache2/apache2.conf, and get SSL:
a2enmod rewrite headers expires
systemctl restart apache2
certbot --apache
- Install MongoDB:
apt install -y mongodb
- Install PHP 7.1:
add-apt-repository ppa:ondrej/php
apt-get update && apt-get install -y php7.1 php7.1-common php7.1-opcache php7.1-mcrypt \
php7.1-cli php7.1-gd php7.1-curl php7.1-mysql php7.1-dev php7.1-xml \
php7.1-mongodb php7.1-intl php7.1-apcu php7.1-imagick php7.1-mbstring php7.1-zip
- Tune PHP settings and restart Apache.
- Install MySQL:
apt-get install -y mysql-server && mysql_secure_installation
In MySQL:
CREATE DATABASE IF NOT EXISTS cocoricodb DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON cocoricodb.* TO 'cocoricouser'@'%' IDENTIFIED BY 'your_db_password';
FLUSH PRIVILEGES;
- Deploy Cocorico:
cd /var/www/html && rm index.html
git clone https://github.com/Cocolabs-SAS/cocorico.git .
curl -s http://getcomposer.org/installer | php
php composer.phar install
mv web/.htaccess.dist web/.htaccess
chmod 744 bin/init-db && ./bin/init-db php --env=dev
chmod 744 bin/init-mongodb && ./bin/init-mongodb php --env=dev
php bin/console assets:install --symlink web --env=dev
chown -R www-data: .
- Configure Apache virtual hosts, test, and restart:
apachectl configtest && service apache2 restart
Notes
- Replace
your_db_password with a strong unique password.
Manage SSL Certificates in InterWorx
This guide explains where InterWorx stores SSL certificates and how to update virtual host configurations to use them.
Certificate File Locations
Private key: /etc/pki/tls/private/localhost.key
Certificate: /etc/pki/tls/certs/localhost.crt
Steps
- After installing or renewing an SSL certificate via the InterWorx panel, certificate files are written to the paths above.
- Find vhosts using different certificate paths:
apachectl -S
- Edit the relevant vhost file to update certificate directives:
SSLCertificateFile /etc/pki/tls/certs/localhost.crt
SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
- Reload Apache:
apachectl configtest && service httpd restart
Fix phpMyAdmin Installation Errors
This guide covers two common phpMyAdmin issues: a missing database user and a 403 Forbidden error on CentOS.
Fix 1: Missing phpMyAdmin Database User
mysql -u root -p
CREATE USER 'phpmyadmin'@'localhost' IDENTIFIED BY 'your_pma_password';
GRANT ALL PRIVILEGES ON phpmyadmin.* TO 'phpmyadmin'@'localhost';
FLUSH PRIVILEGES;
Log in to phpMyAdmin, click the warning banner, and select Click here to fix to create missing tables.
Fix 2: 403 Forbidden on CentOS (Apache 2.4)
Edit /etc/httpd/conf.d/phpMyAdmin.conf and add inside the <Directory> block:
Require all granted
Restart Apache: service httpd restart
Notes
- Replace
your_pma_password with a strong password.
- In production, restrict access by IP rather than using
Require all granted.
Migrate Office 365 Mailboxes to Google Workspace
This guide covers migrating email from Office 365 to Google Workspace using the Google Workspace Migration for Microsoft Exchange (GWMME) tool.
Steps
- Create an impersonation role in Exchange Admin Center:
- Go to Permissions > Admin Roles and create a new role group.
- Add the ApplicationImpersonation and View-Only Configuration roles.
- Add the migration admin account as a member.
- For GoDaddy-hosted O365: In Exchange Admin Center, open Security Administrator > Roles, add Application Impersonation. Under Members, add the admin user.
- Create users in Google Workspace: Create all destination mailbox accounts before starting migration.
- Run GWMME: Configure the Exchange source server and credentials, select mailboxes, and start migration.
Notes
- Impersonation must be configured on the Exchange side before GWMME can access user mailboxes.
Fix Elementor Widgets Not Loading
The "Elementor not loading" error is typically caused by plugin conflicts, insufficient PHP memory, or Apache resource limits.
Steps
- Check for plugin conflicts: Deactivate all plugins except Elementor and Elementor Pro, then reactivate one by one to find the conflict.
- Increase PHP memory limit in
wp-config.php:
define('WP_MEMORY_LIMIT', '256M');
Elementor recommends at least 128 MB.
- Increase Apache limits in
.htaccess:
<IfModule mod_substitute.c>
SubstituteMaxLineLength 30m
</IfModule>
LimitRequestBody 9999999
- Reset .htaccess: Rename it as backup, then go to Settings > Permalinks and Save Changes to regenerate.
- Switch editor loading method: In Elementor > Settings, enable Switch editor loader method.
- Regenerate CSS: Go to Elementor > Tools > Regenerate CSS & Data.
Install Acelle Mail 3.0
Acelle Mail is a self-hosted email marketing platform built on Laravel for sending marketing and transactional emails through your own server or third-party providers.
Prerequisites
- Linux server with PHP 5.6+ (7.1 recommended), extensions: Mbstring, OpenSSL, PDO, Tokenizer, Zip, IMAP
- MySQL 5.x+, Apache or Nginx with mod_rewrite, Composer
Installation with Apache
- Extract Acelle source files and configure an Apache virtual host with DocumentRoot pointing to the
public/ subdirectory:
<VirtualHost *:80>
ServerName yourhost.net
DocumentRoot "/home/your_user/acellemail/public"
<Directory "/home/your_user/acellemail/public">
AllowOverride All
Require all granted
</Directory>
</VirtualHost>
- Set correct ownership:
sudo chown www-data:www-data -R /home/your_user/acellemail
sudo chmod 775 -R /home/your_user/acellemail
- Restart Apache and navigate to
http://yourhost.net/install to run the web wizard.
Notes
- Disable
mod_security on Apache if the installer returns unexpected errors.
Fix phpMyAdmin "count(): Parameter must be an array" Warning on PHP 7.2
phpMyAdmin v4.6.x from Ubuntu repositories is not compatible with PHP 7.2. The recommended fix is upgrading phpMyAdmin to v4.8+.
Fix Option 1: Upgrade phpMyAdmin (Recommended)
Download the latest phpMyAdmin from the official website and replace the existing installation files.
Fix Option 2: Patch sql.lib.php
sudo cp /usr/share/phpmyadmin/libraries/sql.lib.php \
/usr/share/phpmyadmin/libraries/sql.lib.php.bak
sudo nano /usr/share/phpmyadmin/libraries/sql.lib.php
Find: (count($analyzed_sql_results['select_expr'] == 1)
Replace with: ((count($analyzed_sql_results['select_expr']) == 1)
Fix Option 3: Patch plugin_interface.lib.php (for import/export warnings)
sudo cp /usr/share/phpmyadmin/libraries/plugin_interface.lib.php \
/usr/share/phpmyadmin/libraries/plugin_interface.lib.php.bak
sudo nano /usr/share/phpmyadmin/libraries/plugin_interface.lib.php
Find: if (! is_null($options) && count($options) > 0)
Replace with: if (! is_null($options) && count((array)$options) > 0)
Configure Acelle Mail SMTP and Sending Domain
After installing Acelle Mail, complete SMTP and domain configuration to enable email sending.
Steps
- Assign sending permissions: In the Acelle admin dashboard, ensure the required sending permissions are assigned to the user account.
- Create SMTP credentials: Under Sending Server configuration, add an SMTP server with your provider's host, port, username, and password.
- Verify sending domain: In Acelle, go to Sending Domains, add your domain, and retrieve the DNS records to add at your registrar.
- Add DNS records: Add the provided SPF, DKIM, and DMARC records to your domain's DNS.
- Verify: Return to Acelle and click Verify to confirm DNS records resolve correctly.
Notes
- All three items (permissions, SMTP, domain verification) must be configured before campaigns send successfully.
Send Commands Into a Running GNU Screen Session
GNU Screen's -X stuff command sends keystrokes into a named screen session from outside it, useful for scripting interactive programs.
Steps
- Start a named screen session in detached mode:
screen -d -m -S my_session
- Send a command into the session (
\015 emulates pressing Enter):
screen -S my_session -X stuff 'your_command'$(echo -ne '\015')
- Attach to verify:
screen -r my_session
Detach with Ctrl+A then D.
Example
# Terminal 1: create session
screen -S demo_session
# Terminal 2: send command to it
screen -S demo_session -X stuff 'echo HELLO WORLD'$(echo -ne '\015')
Notes
- For reliable automation of interactive programs, use expect instead of
stuff.
- The session must not be password-protected for
-X to work.
Fix Linker Error: cannot find -l<library>
The error /usr/bin/ld: cannot find -l<libraryname> means the development package for a required library is not installed.
Steps
- Identify the missing library from the error, e.g.
/usr/bin/ld: cannot find -lmcpp
- Install the development package:
apt-get install libmcpp-dev
The pattern is lib<name>-dev.
- Retry the build.
Example: Missing Berkeley DB C++ headers
# Error: fatal error: db_cxx.h: No such file or directory
apt-get install libdb++-dev
Notes
- On CentOS/RHEL use
yum install <package>-devel.
- Search for the package:
apt-cache search <libraryname>
Fix "You can't access this shared folder" on Windows 10
Windows 10 blocks access to network shares when unauthenticated guest access is disabled by Group Policy, showing: You can't access this shared folder because your organization's security policies block unauthenticated guest access.
Fix: Enable Insecure Guest Logons via Group Policy
- Press
Win + R, type gpedit.msc, press Enter.
- Navigate to:
Computer Configuration > Administrative Templates > Network > Lanman Workstation
- Double-click Enable insecure guest logons and set to Enabled.
- Click OK and retry accessing the share.
Notes
- This policy was tightened in Windows 10 version 1709.
- Enabling insecure guest logons reduces security. Acceptable on home networks; avoid in corporate environments.
gpedit.msc is available on Windows 10 Pro, Enterprise, and Education only.
Sync IMAP Mailboxes Using imapsync
imapsync copies email from one IMAP server to another, preserving folder structure. It is commonly used after a server migration while DNS propagates.
Steps
- Optionally start a screen session:
screen -S imapsync
- Install imapsync:
yum install imapsync -y
- Run imapsync:
imapsync \
--host1 SOURCE_SERVER_IP \
--user1 user@example.com \
--password1 your_source_password \
--host2 localhost \
--user2 user@example.com \
--password2 your_destination_password
Notes
- Replace password placeholders with actual credentials.
- Run
imapsync --help for options including folder exclusions and dry-run mode.
Remove the DigitalOcean MOTD Welcome Message
DigitalOcean droplets display a welcome message on login via MOTD scripts. This guide shows how to disable or customise it.
Steps
- Locate the MOTD script (one-click droplets:
/etc/update-motd.d/99-one-click; standard Ubuntu: /etc/update-motd.d/00-header).
- Disable the script:
sudo chmod -x /etc/update-motd.d/99-one-click
- Alternatively, edit the script to remove the text. Note:
00-header runs under /bin/dash — use \033 for escape sequences instead of \e.
Verify
Log out and log back in. The welcome message should no longer appear.
Download Google Drive Files from the Shell Using gdrive.sh
gdrive.sh is a shell script for downloading files and folders from Google Drive using a file ID or shareable link.
Usage
# Download by file ID
curl gdrive.sh | bash -s YOUR_FILE_ID
# Download by shareable link
curl gdrive.sh | bash -s "https://drive.google.com/file/d/YOUR_FILE_ID/view"
# Download an entire folder
curl gdrive.sh | bash -s "https://drive.google.com/drive/folders/YOUR_FOLDER_ID"
Install as an Alias
alias gdrive.sh='curl gdrive.sh | bash -s'
gdrive.sh YOUR_FILE_ID
Get the File ID
In Google Drive, right-click a file, select Get shareable link, and copy the ID from the URL (the string after /d/ or ?id=).
Install npm Peer Dependencies with install-peerdeps
Since npm v3, peer dependencies are not installed automatically. install-peerdeps installs a package and all its peer dependencies in one command.
Installation
npm install -g install-peerdeps
Usage
cd my-project-directory
# Install with peers
install-peerdeps <package-name>
# As a dev dependency
install-peerdeps <package-name> --dev
# Preview without installing
install-peerdeps <package-name> --dry-run
Example
install-peerdeps eslint-config-airbnb --dev
Notes
- The tool auto-detects Yarn and prompts accordingly.
- Use
--extra-args to pass additional flags through to npm or Yarn.
Install Yellowfin BI on Ubuntu
Yellowfin is a business intelligence platform distributed as a self-contained JAR installer. This guide covers installation on Ubuntu with MySQL, Java, and Nginx reverse proxy with SSL.
Steps
- Create a dedicated user and install dependencies:
adduser yellowfin
usermod -aG sudo yellowfin
su - yellowfin
sudo apt install mysql-server openjdk-8-jre-headless
sudo apt-get install libmysql-java
sudo nano /etc/java-8-openjdk/accessibility.properties
# Comment out the last line
- Run the Yellowfin installer:
sudo mv yellowfin-*.jar /home/yellowfin/
sudo java -jar /home/yellowfin/yellowfin-*.jar
- Create a systemd service and enable it:
sudo cp /etc/systemd/system/sshd.service /etc/systemd/system/yellowfin.service
sudo nano /etc/systemd/system/yellowfin.service
sudo systemctl daemon-reload
sudo systemctl enable yellowfin
sudo systemctl start yellowfin
- Install Nginx and configure reverse proxy with SSL (Yellowfin runs on port 8080):
sudo apt install nginx
sudo certbot --nginx -d yourdomain.com
Add to Nginx server block:
location / {
proxy_pass http://127.0.0.1:8080/;
proxy_set_header Host $host;
}
Download Files from FTP Using wget
wget can download files from FTP servers directly, including recursive directory downloads with authentication.
Basic Usage
wget -r --ftp-user="your_ftp_user" --ftp-password="your_ftp_password" \
ftp://ftp.example.com/path/to/dir/
Alternative Syntax
wget -m ftp://your_username:your_password@ftp.example.com/dir/*
Exclude a Directory
wget -m -X /path/to/exclude ftp://your_username:your_password@ftp.example.com/www/*
Flatten Directory Structure
wget -r --no-parent -nH --cut-dirs=1 \
--ftp-user="your_ftp_user" \
--ftp-password="your_ftp_password" \
ftp://ftp.example.com/web/targetdir/
Mount FTP as a Drive
curlftpfs -o user=your_ftp_user:your_ftp_password ftp://ftp.example.com /mnt/ftp
Notes
- Replace
your_ftp_user and your_ftp_password with actual credentials.
Upgrade Red5 Pro Media Server
Upgrade Red5 Pro by extracting the new version alongside the existing install, copying config files, and swapping directories.
Steps
- Create a directory and extract the new release:
cd /usr/local/
mkdir red5pro_new && cd red5pro_new
unzip /home/ubuntu/red5pro-server-new-version.zip
- Copy configuration files from the old install:
cp /usr/local/red5pro/conf/red5.properties conf/
cp /usr/local/red5pro/conf/jee-container.xml conf/
cp /usr/local/red5pro/conf/red5-common.xml conf/
cp /usr/local/red5pro/conf/cloudstorage-plugin.properties conf/
cp /usr/local/red5pro/conf/simple-auth-plugin.properties conf/
cp /usr/local/red5pro/conf/simple-auth-plugin.credentials conf/
cp /usr/local/red5pro/conf/cluster.xml conf/
cp /usr/local/red5pro/conf/webrtc-plugin.properties conf/
cp /usr/local/red5pro/webapps/live/WEB-INF/red5-web.xml webapps/live/WEB-INF/
cp /usr/local/red5pro/webapps/streammanager/WEB-INF/web.xml webapps/streammanager/WEB-INF/
cp /usr/local/red5pro/webapps/api/WEB-INF/red5-web.properties webapps/api/WEB-INF/
- Stop, swap, and restart:
service red5pro stop
cd /usr/local
mv red5pro red5pro_old
mv red5pro_new red5pro
service red5pro start
Notes
- On Ubuntu with releases newer than 5.2.0, set
openssl.enabled=false in conf/webrtc-plugin.properties to avoid libcrypto compatibility issues.
Install Red5 Pro with SSL
This guide covers installing Red5 Pro media server with a Let's Encrypt SSL certificate for HTTPS and RTMPS support.
Steps
- Install Certbot and obtain a certificate:
apt-get install software-properties-common
add-apt-repository universe
add-apt-repository ppa:certbot/certbot -y
apt-get update && apt-get install certbot
certbot certonly --standalone --email admin@yourdomain.com --agree-tos \
-d yourdomain.com -d www.yourdomain.com
- Generate a PKCS12 keystore (use a strong
your_keystore_password):
openssl pkcs12 -export \
-in /etc/letsencrypt/live/yourdomain.com/fullchain.pem \
-inkey /etc/letsencrypt/live/yourdomain.com/privkey.pem \
-out /etc/letsencrypt/live/yourdomain.com/fullchain_and_key.p12 \
-name tomcat
- Import into a Java keystore and create truststore:
keytool -importkeystore \
-deststorepass your_keystore_password -destkeypass your_keystore_password \
-destkeystore /etc/letsencrypt/live/yourdomain.com/keystore.jks \
-srckeystore /etc/letsencrypt/live/yourdomain.com/fullchain_and_key.p12 \
-srcstoretype PKCS12 -srcstorepass your_keystore_password -alias tomcat
keytool -export -alias tomcat \
-file /etc/letsencrypt/live/yourdomain.com/tomcat.cer \
-keystore /etc/letsencrypt/live/yourdomain.com/keystore.jks \
-storepass your_keystore_password -noprompt
keytool -import -trustcacerts -alias tomcat \
-file /etc/letsencrypt/live/yourdomain.com/tomcat.cer \
-keystore /etc/letsencrypt/live/yourdomain.com/truststore.jks \
-storepass your_keystore_password -noprompt
- Install Red5 Pro using the official installer script:
cd /opt
git clone https://github.com/red5pro/red5pro-installer
cd red5pro-installer && chmod +x *.sh
./red5proInstaller.sh
- Update
/usr/local/red5pro/conf/red5.properties: set https.port=443 and update RTMPS keystore/truststore paths to the Let's Encrypt files.
- Update
/usr/local/red5pro/conf/jee-container.xml: comment out HTTP connector, uncomment HTTPS connector.
- Restart:
service red5pro restart
Certificate Renewal
certbot renew
Install Zammad Helpdesk on Ubuntu
Zammad is an open-source helpdesk platform. This guide covers installation on Ubuntu 18.04 with Elasticsearch 7.x and Let's Encrypt SSL via Nginx.
Steps
- Install Elasticsearch 7.x:
apt-get install -y apt-transport-https sudo wget zip curl
echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | \
sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
apt-get update && apt-get -y install elasticsearch
/usr/share/elasticsearch/bin/elasticsearch-plugin install ingest-attachment
systemctl restart elasticsearch && systemctl enable elasticsearch
- Install Zammad:
wget -qO- https://dl.packager.io/srv/zammad/zammad/key | sudo apt-key add -
wget -O /etc/apt/sources.list.d/zammad.list \
https://dl.packager.io/srv/zammad/zammad/stable/installer/ubuntu/18.04.repo
apt-get update && apt-get install -y zammad
- Connect Zammad to Elasticsearch:
zammad run rails r "Setting.set('es_url', 'http://localhost:9200')"
zammad run rake searchindex:rebuild
- Install Certbot and configure SSL:
apt-get install -y certbot python3-certbot-nginx
certbot --nginx
Backup and Restore
mkdir -p /var/tmp/zammad_backup
mv /opt/zammad/contrib/backup/config.dist /opt/zammad/contrib/backup/config
/opt/zammad/contrib/backup/zammad_backup.sh
Move ExpressionEngine CMS to Another Server
This guide covers migrating an ExpressionEngine installation to a new server.
Steps
- Verify server compatibility: Upload and run the ExpressionEngine Server Compatibility Wizard on the new server.
- Synchronise templates: Go to Design > Templates > Template Manager > Synchronise Templates, select all, and click Submit.
- Clear caches: Go to Tools > Data > Clear Caching, select All Caches, and click Submit.
- Back up database and files: Export the database and archive all EE files.
- Set up the new database: Create an empty database and import the SQL backup.
- Copy files: Transfer
admin.php, index.php, images/, system/, themes/.
- Set permissions:
# chmod 666
system/expressionengine/config/config.php
system/expressionengine/config/database.php
# chmod 777
system/expressionengine/cache/
images/uploads/
- Update database.php: Edit database host, name, username, and password for the new server.
- Log in and update paths in the Control Panel (General Configuration, File Upload Preferences, etc.).
Find a DNS Zone Transfer Misconfiguration
A misconfigured DNS server allowing unrestricted zone transfers (AXFR) can expose all DNS records to anyone who requests them.
Types of Zone Transfer
- AXFR: Full zone transfer — returns the complete DNS zone.
- IXFR: Incremental zone transfer — returns only changes since a specified serial.
Test on Linux
# Find name servers
host -t ns example.com
# Attempt a full zone transfer
host -t axfr example.com ns1.example.com
# Using dig
dig @ns1.example.com example.com AXFR
Test on Windows (nslookup)
nslookup -type=ns example.com
nslookup
> server ns1.example.com
> set type=any
> ls -d example.com
A misconfigured server returns all DNS records. A properly configured server returns a transfer refused error.
Remediation
Restrict zone transfers in BIND:
allow-transfer { secondary_nameserver_ip; };
Notes
- Only test against domains you own or have explicit permission to test.
Nagios XI CVE-2021-25296 Remote Command Injection
CVE-2021-25296 is a remote command injection vulnerability in Nagios XI 5.7.5 affecting the Windows WMI Configuration Wizard. Attackers used it to deploy the XMRig cryptocurrency miner.
Detect Compromise
ps -ef | grep 'systemd-py-run.sh\|workrun.sh'
ls /usr/lib/dev/
ls /tmp/usr/lib/
Remediation
- Upgrade Nagios XI to the latest version (vulnerability is fixed in current releases).
- If upgrading immediately is not possible, apply the code fix in:
/usr/local/nagiosxi/html/includes/configwizards/windowswmi/windowswmi.inc.php
The fix adds escapeshellarg() validation on the plugin_output_len parameter.
- If compromised: kill the miner process and delete the malicious scripts.
Notes
- Exploitation requires an authenticated user account. Restrict access to the Nagios XI interface and rotate credentials as part of remediation.
Convert Images to WebP and Serve Them with Apache or Nginx
WebP provides smaller file sizes than JPEG and PNG. This guide covers converting images using cwebp and serving them with content negotiation.
Install cwebp
# Ubuntu
sudo apt-get install webp
# CentOS
sudo yum install libwebp-tools
Convert Images
# Single image
cwebp -q 80 image.jpg -o image.webp
# Batch convert JPEGs
for f in *.jpg; do cwebp -q 80 "$f" -o "${f%.jpg}.webp"; done
Serve WebP with Apache
Add to .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_FILENAME} (.*)\.(png|jpg)$
RewriteCond %1\.webp -f
RewriteRule (.*)\.(png|jpg)$ $1.webp [T=image/webp,E=accept:1]
</IfModule>
<IfModule mod_headers.c>
Header append Vary Accept env=REDIRECT_accept
</IfModule>
AddType image/webp .webp
Serve WebP with Nginx
map $http_accept $webp_suffix {
default "";
"~*webp" ".webp";
}
location ~* ^/(.+)\.(png|jpg)$ {
try_files $uri$webp_suffix $uri =404;
add_header Vary Accept;
}
Install SearXNG Privacy-Respecting Search Engine with Docker
SearXNG is a self-hostable metasearch engine. This guide covers installing it on Ubuntu using Docker and Docker Compose.
Steps
- Install prerequisites:
apt update && apt upgrade -y
apt install git ca-certificates curl gnupg lsb-release -y
- Clone SearXNG Docker repository:
cd /usr/local
git clone https://github.com/searxng/searxng-docker.git
- Install Docker:
mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
apt update
apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
- Install Docker Compose:
curl -L https://github.com/docker/compose/releases/download/v2.9.0/docker-compose-linux-x86_64 \
-o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
- Configure and start SearXNG:
cd /usr/local/searxng-docker
nano .env # Set SEARXNG_HOSTNAME and SEARXNG_SECRET_KEY
docker-compose up -d
Verify
Access your configured domain or http://your-server-ip:8080.
Write README.md Files Using Markdown
Markdown is a lightweight markup language for formatting plain text. README.md files written in Markdown are rendered by GitHub, GitLab, and most code repositories.
Headings
# Heading 1
## Heading 2
### Heading 3
Text Formatting
**bold**
_italic_
~~strikethrough~~
`inline code`
> blockquote
Lists
# Unordered
- Item one
- Item two
# Ordered
1. First
2. Second
Code Blocks
```bash
sudo apt-get update
```
Links and Images
[Link text](https://example.com)

Tables
| Column A | Column B |
|----------|----------|
| Value 1 | Value 2 |
JavaScript Redirect Using window.location.href
To redirect a browser using JavaScript, assign the destination URL to window.location.href. Include an HTML meta refresh fallback for users without JavaScript.
JavaScript Redirect
<script>
window.location.href = "https://newdomain.example.com";
</script>
With HTML Meta Refresh Fallback
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=https://newdomain.example.com">
<script>window.location.href = "https://newdomain.example.com";</script>
</head>
<body>
<p>If you are not redirected, <a href="https://newdomain.example.com">click here</a>.</p>
</body>
</html>
Notes
- For permanent redirects, prefer a server-side 301 redirect for performance and SEO.
window.location.replace("url") redirects without adding the current page to browser history.
Change PrestaShop Site URL in the Database
When migrating a PrestaShop site to a new domain, update the URL in the database. PrestaShop 1.7+ stores the URL in two tables.
Preferred Method: Admin Panel
Go to Configure > Shop Parameters > Traffic & SEO > Set Shop URL, enter the new URL, and click Save.
Database Method (When Admin Panel is Inaccessible)
-- Find current domain settings
SELECT * FROM `ps_configuration` WHERE name LIKE '%PS_SHOP_DOMAIN%';
-- Update the domain
UPDATE `ps_configuration` SET value = 'newdomain.com'
WHERE name = 'PS_SHOP_DOMAIN';
UPDATE `ps_configuration` SET value = 'newdomain.com'
WHERE name = 'PS_SHOP_DOMAIN_SSL';
-- PrestaShop 1.7+: also update ps_shop_url
UPDATE `ps_shop_url`
SET domain = 'newdomain.com', domain_ssl = 'newdomain.com'
WHERE id_shop = 1;
-- Disable SSL if the new URL does not have HTTPS
UPDATE `ps_configuration` SET value = '0' WHERE name = 'PS_SSL_ENABLED';
UPDATE `ps_configuration` SET value = '0' WHERE name = 'PS_SSL_ENABLED_EVERYWHERE';
Notes
- The default table prefix is
ps_. Substitute your custom prefix if you used one during installation.
- If redirects persist, check the
.htaccess file and clear your browser cache.
Install Let's Encrypt SSL for Unifi Controller on Raspberry Pi
The Unifi Controller uses a self-signed certificate by default. This guide covers installing a Let's Encrypt certificate to eliminate browser security warnings.
Prerequisites
- A registered domain with an A record pointing to your public IP
- Port 80 forwarded through your router to the Raspberry Pi
- Certbot installed
- A local DNS entry mapping
unifi.yourdomain.com to the Pi's local IP
Create a Local DNS Entry
On EdgeRouter:
configure
set system static-host-mapping host-name unifi.yourdomain.com inet 192.168.0.201
commit && save
On Windows, add to %windir%\System32\drivers\etc\hosts:
192.168.0.201 unifi.yourdomain.com
Steps
- Obtain a Let's Encrypt certificate:
sudo apt-get install certbot
sudo certbot certonly --standalone -d unifi.yourdomain.com
- Download and configure the SSL import script:
sudo wget https://raw.githubusercontent.com/stevejenkins/unifi-linux-utils/master/unifi_ssl_import.sh \
-O /usr/local/bin/unifi_ssl_import.sh
sudo chmod +x /usr/local/bin/unifi_ssl_import.sh
sudo nano /usr/local/bin/unifi_ssl_import.sh
Set your domain and Unifi keystore password in the script.
- Run the script and restart the controller:
sudo /usr/local/bin/unifi_ssl_import.sh
sudo service unifi restart
Automate Renewal
0 3 1 * * certbot renew --quiet && /usr/local/bin/unifi_ssl_import.sh
Configure MTA-STS for Email Security
MTA-STS tells sending mail servers to use TLS when delivering email to your domain, helping prevent downgrade attacks and eavesdropping.
Policy File
Host a plain-text file at https://mta-sts.yourdomain.com/.well-known/mta-sts.txt:
version: STSv1
mode: enforce
mx: mail.yourdomain.com
mx: alt1.aspmx.l.google.com
mx: alt2.aspmx.l.google.com
mx: alt3.aspmx.l.google.com
mx: alt4.aspmx.l.google.com
mx: aspmx.l.google.com
max_age: 604800
Required DNS Records
A record for mta-sts.yourdomain.com pointing to your web server.
TXT record to publish the policy:
_mta-sts.yourdomain.com TXT "v=STSv1; id=YYYYMMDD01"
Optional TLS reporting:
_smtp._tls.yourdomain.com TXT "v=TLSRPTv1; rua=mailto:tlsrpt@yourdomain.com"
Mode Options
- testing: Failures are reported but not enforced. Start here.
- enforce: Sending servers must use TLS or the message is rejected.
- none: Policy disabled.
Notes
- The policy file must be served over HTTPS on the
mta-sts subdomain.
- Update the
id value in the _mta-sts TXT record whenever the policy file changes.
max_age is in seconds: 604800 = 7 days.