🐧

Ubuntu16 18

20 notes  •  Linux & Server Admin

Install and Configure GitLab CE on Ubuntu 16.04

This guide walks through installing GitLab Community Edition on a fresh Ubuntu 16.04 server, configuring the firewall, and performing initial setup through the web interface.

Prerequisites

  • Ubuntu 16.04 server with at least 2 CPU cores and 2 GB RAM
  • A non-root user with sudo privileges
  • A domain name or static IP address pointed at the server
  • UFW firewall configured (SSH allowed)

Steps

1. Install Dependencies

Update the package index and install the required packages. Select Internet Site when the Postfix installer prompts for mail configuration, then enter your server's domain name.

sudo apt-get update
sudo apt-get install -y ca-certificates curl openssh-server postfix

2. Add the GitLab Repository

Download and run the official GitLab repository setup script. Inspect the script before running if desired.

cd /tmp
curl -LO https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh
less /tmp/script.deb.sh        # optional review
sudo bash /tmp/script.deb.sh

3. Install GitLab CE

sudo apt-get install -y gitlab-ce

4. Run Initial Configuration

This automated step initialises GitLab using information detected from the server.

sudo gitlab-ctl reconfigure

5. Open Firewall Ports

sudo ufw allow http
sudo ufw allow https
sudo ufw allow OpenSSH
sudo ufw status

6. First Login

Open a browser and navigate to your server's domain name or IP address:

http://your_domain_or_IP

On first visit you are prompted to set a password for the root administrator account. After setting the password, log in with username root.

Verify

sudo gitlab-ctl status

All services (unicorn, sidekiq, postgresql, redis, nginx, etc.) should show run: status.

Troubleshooting

  • Reconfigure fails — check /var/log/gitlab/reconfigure.log for details.
  • Port 80 blocked — ensure sudo ufw allow http was run and the cloud provider security group also allows port 80.
  • Low memory — GitLab requires at least 2 GB RAM; add swap if necessary before running reconfigure.
  • Postfix not needed — if you use an external SMTP service, select No configuration during the Postfix prompt and configure SMTP settings in /etc/gitlab/gitlab.rb later.

Set Up a LAMP Stack on Ubuntu 16.04 with PHP 7, MariaDB, and phpMyAdmin

This guide covers installing a full LAMP (Linux, Apache, MariaDB, PHP) stack on Ubuntu 16.04, including phpMyAdmin for database management and UFW firewall configuration.

Prerequisites

  • Ubuntu 16.04 server with a non-root sudo user
  • Root or sudo access

Steps

1. Configure UFW Firewall

sudo apt update
sudo apt-get install -y ufw
sudo ufw enable
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow ssh
sudo ufw allow 80
sudo ufw allow https
sudo ufw status

2. Install Apache

sudo apt install -y apache2
apache2 -v

Back up the default configuration before editing:

sudo cp /etc/apache2/apache2.conf /etc/apache2/apache2.conf.bak
sudo nano /etc/apache2/apache2.conf
sudo service apache2 restart

3. Install PHP 7.0

sudo apt-get install -y php7.0 libapache2-mod-php7.0 php7.0-cli   php7.0-common php7.0-mbstring php7.0-gd php7.0-intl php7.0-xml   php7.0-mysql php7.0-mcrypt php7.0-zip php7.0-curl php7.0-json
php -v

4. Install MariaDB

sudo apt install -y mariadb-server mariadb-client
sudo mysql_secure_installation

Follow the prompts to set a root password and remove anonymous users and test databases.

5. Install phpMyAdmin

sudo apt install -y php-gettext phpmyadmin

Select apache2 when prompted for the web server. If phpMyAdmin needs to be reconfigured later:

sudo dpkg-reconfigure phpmyadmin

6. Allow MySQL Port (Optional — for Remote Access)

sudo ufw allow in on eth0 to any port 3306
sudo ufw status

7. Install Microsoft ODBC Driver (Optional — for SQL Server connectivity)

sudo apt-get install -y unixodbc libgss3 odbcinst

# Add Microsoft repository
curl https://packages.microsoft.com/keys/microsoft.asc | sudo apt-key add -
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list   | sudo tee /etc/apt/sources.list.d/mssql-release.list

sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17 mssql-tools unixodbc-dev

echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc

Verify

apache2 -v
php -v
mysql --version

Visit http://your_server_ip/phpmyadmin to confirm phpMyAdmin is accessible.

Troubleshooting

  • phpMyAdmin shows 404 — run sudo ln -s /etc/phpmyadmin/apache.conf /etc/apache2/conf-available/phpmyadmin.conf && sudo a2enconf phpmyadmin && sudo service apache2 reload.
  • MariaDB access denied — log in as root with sudo mysql -u root and reset the password.
  • PHP extensions missing — install individually, e.g. sudo apt-get install php7.0-curl, then restart Apache.

Manage Services on Ubuntu with systemd

This guide covers the essential systemctl commands for managing services, targets, and system state on Ubuntu systems that use systemd.

Prerequisites

  • Ubuntu 15.04 or later (systemd is the default init system)
  • A user with sudo privileges

Steps

1. Check the Default Target (Runlevel)

systemctl get-default

Common values: multi-user.target (server) and graphical.target (desktop).

2. List Active Targets

systemctl list-units --type=target

3. Start, Stop, and Restart Services

sudo systemctl start <service>
sudo systemctl stop <service>
sudo systemctl restart <service>
sudo systemctl reload <service>

4. Enable and Disable Services at Boot

sudo systemctl enable <service>
sudo systemctl disable <service>

5. Check Service Status

systemctl status <service>

6. List All Running Services

systemctl list-units --type=service --state=running

7. Switch to a Different Target Interactively

sudo systemctl isolate multi-user.target

8. View Service Logs

journalctl -u <service> -n 50 --no-pager

Verify

systemctl is-active <service>
systemctl is-enabled <service>

Notes

  • systemctl isolate changes the current target immediately but does not persist across reboots — use systemctl set-default to change the default permanently.
  • Use journalctl -xe to view recent journal entries with context when diagnosing a failed service.
  • Replace <service> with the unit name, e.g. nginx, apache2, mysql.

Fix "Unable to locate package msodbcsql" on Ubuntu

When running apt-get install msodbcsql without first adding the Microsoft repository, apt reports "Unable to locate package". This guide adds the correct Microsoft package source and installs the ODBC driver and SQL Server tools.

Prerequisites

  • Ubuntu 16.04 or 18.04
  • A user with sudo privileges
  • curl installed (sudo apt-get install curl)

Steps

1. Add the Microsoft GPG Key

sudo su
curl https://packages.microsoft.com/keys/microsoft.asc | apt-key add -

2. Add the Microsoft Package Repository

Choose the line matching your Ubuntu version:

# Ubuntu 16.04
curl https://packages.microsoft.com/config/ubuntu/16.04/prod.list   > /etc/apt/sources.list.d/mssql-release.list

# Ubuntu 18.04
curl https://packages.microsoft.com/config/ubuntu/18.04/prod.list   > /etc/apt/sources.list.d/mssql-release.list

3. Update Package Lists and Install

exit   # back to normal sudo user
sudo apt-get update
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql17

4. Install SQL Server Command-Line Tools (Optional)

sudo ACCEPT_EULA=Y apt-get install -y mssql-tools
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bash_profile
echo 'export PATH="$PATH:/opt/mssql-tools/bin"' >> ~/.bashrc
source ~/.bashrc

5. Install UnixODBC Development Headers (Optional)

sudo apt-get install -y unixodbc-dev

Verify

sqlcmd -?

You should see the sqlcmd usage output confirming the tools are on your PATH.

Troubleshooting

  • EULA not accepted — the ACCEPT_EULA=Y environment variable must prefix the install command; without it the package will not install.
  • Wrong OS version — double-check which repository URL you used; mixing 16.04 and 18.04 URLs causes package conflicts.
  • GPG errors on apt update — re-run the apt-key add step to ensure the Microsoft key is correctly imported.

Install the ELK Stack on Ubuntu 18.04

This guide installs Elasticsearch, Logstash, and Kibana (the ELK stack) on Ubuntu 18.04 Bionic Beaver using the official Elastic APT repository and Nginx as a reverse proxy for Kibana.

Prerequisites

  • Ubuntu 18.04 with root or sudo access
  • At least 2 GB RAM (4 GB recommended)
  • Java 8 (Logstash does not support Java 10/11 in the 6.x release)
  • Nginx installed (disable Apache or change its port if running)

Steps

1. Install Dependencies

sudo apt install -y openjdk-8-jre apt-transport-https wget nginx

If openjdk-11-jre is already installed, remove it first:

sudo apt remove openjdk-11-jre

2. Add the Elastic APT Repository

wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -

echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main"   | sudo tee /etc/apt/sources.list.d/elastic.list

sudo apt update

3. Install Elasticsearch

sudo apt install -y elasticsearch

Enable and start the service:

sudo systemctl enable elasticsearch
sudo systemctl start elasticsearch

4. Install Kibana

sudo apt install -y kibana

Configure Kibana to listen on localhost only (Nginx will proxy it):

sudo nano /etc/kibana/kibana.yml

Set: server.host: "localhost"

sudo systemctl enable kibana
sudo systemctl start kibana

5. Configure Nginx Reverse Proxy for Kibana

sudo nano /etc/nginx/sites-available/kibana

Add:

server {
    listen 80;
    server_name your_domain_or_IP;

    location / {
        proxy_pass http://localhost:5601;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
sudo ln -s /etc/nginx/sites-available/kibana /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

6. Install Logstash

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

Verify

# Elasticsearch
curl -X GET "localhost:9200"

# Service statuses
sudo systemctl status elasticsearch kibana logstash

Open http://your_domain_or_IP in a browser to access the Kibana dashboard.

Troubleshooting

  • Elasticsearch fails to start — check journalctl -u elasticsearch -n 50; a common cause is insufficient heap memory. Edit /etc/elasticsearch/jvm.options to reduce -Xms and -Xmx.
  • Logstash crashes with Java error — ensure only Java 8 is installed; Logstash 6.x does not support Java 10 or 11.
  • Kibana shows "Kibana server is not ready yet" — wait 30–60 seconds after starting for Kibana to connect to Elasticsearch, or check journalctl -u kibana.
  • Nginx 502 error — confirm Kibana is running on port 5601 with ss -tlnp | grep 5601.

Run ASP.NET Core Applications on Ubuntu with Apache

This guide explains how to publish an ASP.NET Core web application and host it on an Ubuntu server using Apache as a reverse proxy, with the .NET Core runtime installed via the official Microsoft packages.

Prerequisites

  • Ubuntu 16.04 or 18.04 server with sudo access
  • Apache installed and running
  • An ASP.NET Core application ready to publish
  • SSH access to the server

Steps

1. Install the .NET Core Runtime on the Server

Add the Microsoft package repository and install the runtime:

# Ubuntu 18.04
wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update
sudo apt-get install -y aspnetcore-runtime-2.2

# Ubuntu 16.04 — replace the config URL with:
# https://packages.microsoft.com/config/ubuntu/16.04/packages-microsoft-prod.deb

2. Publish the Application from Visual Studio / CLI

Run this on your development machine:

dotnet publish --configuration Release --output ./publish

Transfer the published output to the server (adjust paths as needed):

scp -r ./publish user@your_server:/var/www/myapp

3. Test the Application Runs

cd /var/www/myapp
dotnet MyApp.dll

The app should start and listen on a port (default 5000). Press Ctrl+C to stop.

4. Create a systemd Service

Create a service unit so the app starts automatically:

sudo nano /etc/systemd/system/myapp.service

Paste the following (adjust User, WorkingDirectory, and ExecStart):

[Unit]
Description=My ASP.NET Core App
After=network.target

[Service]
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/dotnet /var/www/myapp/MyApp.dll
Restart=always
RestartSec=10
SyslogIdentifier=myapp
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production

[Install]
WantedBy=multi-user.target
sudo systemctl enable myapp
sudo systemctl start myapp
sudo systemctl status myapp

5. Configure Apache as a Reverse Proxy

sudo a2enmod proxy proxy_http headers rewrite
sudo nano /etc/apache2/sites-available/myapp.conf

Add:

<VirtualHost *:80>
    ServerName your_domain_or_IP
    ProxyPreserveHost On
    ProxyPass / http://localhost:5000/
    ProxyPassReverse / http://localhost:5000/
    ErrorLog ${APACHE_LOG_DIR}/myapp_error.log
    CustomLog ${APACHE_LOG_DIR}/myapp_access.log combined
</VirtualHost>
sudo a2ensite myapp.conf
sudo apache2ctl configtest
sudo systemctl restart apache2

Verify

sudo systemctl status myapp
curl http://localhost:5000

Open http://your_domain_or_IP in a browser to confirm the app is being served through Apache.

Troubleshooting

  • dotnet: command not found — ensure the .NET runtime package installed correctly and /usr/bin/dotnet exists.
  • 502 Bad Gateway from Apache — verify the app service is running with systemctl status myapp and listening on port 5000 with ss -tlnp | grep 5000.
  • Permission denied errors — ensure the www-data user has read access to /var/www/myapp: sudo chown -R www-data:www-data /var/www/myapp.
  • App crashes on startup — run dotnet MyApp.dll manually as the app user to see the error output directly.

Remove a GPG Key Added with apt-key

When a repository is no longer needed, the GPG key used to verify its packages should also be removed from the system keyring. This guide shows how to list keys and remove a specific one using apt-key.

Prerequisites

  • Ubuntu 14.04–20.04 (for systems using the legacy apt-key workflow)
  • A user with sudo privileges

Steps

1. List All Trusted Keys

sudo apt-key list

Each key entry looks similar to this:

pub   1024R/B455BEF0 2010-07-29
uid                  Launchpad clicompanion-nightlies

On Ubuntu 16.10 and later, the short key ID is the last 8 characters of the long fingerprint shown on the pub line. For example, if the fingerprint ends in EFE21092, the key ID is EFE21092.

2. Remove the Key

Use the key ID (the 8-character hex string from the pub line):

sudo apt-key del B455BEF0

3. Confirm Removal

apt-key list | grep -i <name-or-partial-uid>

No output means the key has been removed.

Notes

  • On Ubuntu 22.04 and later, apt-key is deprecated. Use signed-by keyring files in /etc/apt/trusted.gpg.d/ instead. Delete the corresponding .gpg file to remove a key.
  • Also remove the repository's .list file from /etc/apt/sources.list.d/ so apt update no longer attempts to fetch it.
  • Run sudo apt update after removing the key and source list to clear any related warnings.

Manage Python Versions with update-alternatives

When multiple Python versions are installed side by side, update-alternatives lets you switch the default python command between them without manually editing symlinks.

Prerequisites

  • Ubuntu 16.04 or later
  • Two or more Python versions installed (e.g. python3.6 and python3.8)
  • A user with sudo privileges

Steps

1. Register Python Versions with update-alternatives

The --install syntax is: update-alternatives --install <link> <name> <path> <priority>

sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.6 1
sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 2

Higher priority numbers are selected automatically when no manual choice has been made.

2. Switch Between Versions Interactively

sudo update-alternatives --config python

An interactive menu lists all registered versions. Enter the selection number to switch.

3. Set a Specific Version Non-Interactively

sudo update-alternatives --set python /usr/bin/python3.6

Verify

python --version

Notes

  • This configures the bare python command. To also manage python3, register both versions under the name python3 separately.
  • Virtual environments (venv, virtualenv) are unaffected by this system-wide setting and use whichever interpreter they were created with.
  • To remove a version from the alternatives group: sudo update-alternatives --remove python /usr/bin/python3.6.

Fix "Could not get lock /var/cache/apt/archives/lock" Error

The error E: Could not get lock /var/cache/apt/archives/lock occurs when another process is already using the APT package manager. This guide explains how to identify and resolve the conflict.

Prerequisites

  • Ubuntu or Debian system
  • A user with sudo privileges

Steps

1. Wait for the Existing Process to Finish

The most common cause is an automatic background update. Check whether another APT process is running:

ps aux | grep -i apt

If an update is in progress, wait for it to complete, then retry your command.

2. Close Any Open Package Managers

If the Ubuntu Software Center or Synaptic is open, close it and try again.

3. Kill Stale APT Processes

sudo killall apt-get
sudo killall apt

4. Remove Stale Lock Files

Only do this if you are certain no APT process is running (verify with ps aux | grep apt returning no results):

sudo rm /var/lib/apt/lists/lock
sudo rm /var/cache/apt/archives/lock
sudo rm /var/lib/dpkg/lock
sudo rm /var/lib/dpkg/lock-frontend

5. Reconfigure dpkg and Update

sudo dpkg --configure -a
sudo apt-get update

Verify

sudo apt-get install -f

If this completes without lock errors, the issue is resolved.

Troubleshooting

  • Lock reappears immediately — a background service such as unattended-upgrades is running. Wait for it to complete or temporarily stop it: sudo systemctl stop unattended-upgrades.
  • dpkg is in an inconsistent state after removal — run sudo dpkg --configure -a followed by sudo apt-get install -f to repair broken packages.
  • Do not routinely delete lock files — removing locks while APT is running can corrupt the package database. Only remove them when you have confirmed no APT process is active.

Fix MongoDB Wire Version Error with PHP Driver

The error "Server reports wire version 2, but this version of libmongoc requires at least 3" occurs when the system-packaged PHP MongoDB driver is built against a newer libmongoc than your MongoDB server supports. The fix is to replace the system package with the PECL extension at the correct version.

Prerequisites

  • Ubuntu 18.04 or Linux Mint 19 (or similar Ubuntu-based system)
  • PHP 7.x with php-pear available
  • A user with sudo privileges

Steps

1. Remove the System-Packaged MongoDB Driver

sudo apt-get remove --auto-remove php-mongodb php7.2-mongodb

2. Install PEAR/PECL if Not Already Present

sudo apt-get update
sudo apt-get install -y php-pear php-dev

3. Install the MongoDB Extension via PECL

Install a version of the driver compatible with your MongoDB server (1.4.x works with MongoDB 2.x/3.x wire protocol):

sudo pecl install mongodb-1.4.4

4. Enable the Extension in php.ini

echo "extension=mongodb.so" | sudo tee -a /etc/php/7.2/apache2/php.ini
echo "extension=mongodb.so" | sudo tee -a /etc/php/7.2/cli/php.ini

5. Restart the Web Server

sudo systemctl reload apache2

Verify

php -m | grep mongodb

You should see mongodb in the output. Also verify the application can connect to your MongoDB instance without the wire version error.

Troubleshooting

  • pecl: command not found — install PEAR first: sudo apt-get install php-pear.
  • Build fails during pecl install — ensure PHP development headers are installed: sudo apt-get install php-dev.
  • Extension not loaded after reload — confirm the extension=mongodb.so line was added to the correct php.ini for your SAPI (CLI vs Apache) and check php -i | grep mongodb.
  • Choosing the right version — check the mongodb/mongo-php-driver GitHub release notes for the wire protocol version your MongoDB server requires.

Fix hostnamectl Errors Caused by Missing D-Bus on Debian/Ubuntu

When hostnamectl fails with "Failed to create bus connection: No such file or directory", the D-Bus system daemon is either not installed or not running. This guide diagnoses and resolves the issue.

Prerequisites

  • Debian 9 or Ubuntu 16.04/18.04
  • A user with sudo privileges
  • systemd as the init system (PID 1)

Steps

1. Check Whether D-Bus is Installed

sudo dpkg -l | grep dbus

Expected output includes a line beginning with ii dbus. If the output is blank, D-Bus is not installed.

2. Install D-Bus

sudo apt-get install -y dbus

3. Check the D-Bus Service Status

sudo systemctl status dbus.service dbus.socket

Both units should show Active: active (running).

4. Start and Enable D-Bus if Not Running

sudo systemctl enable dbus
sudo systemctl start dbus

5. Retry hostnamectl

hostnamectl

Verify

systemctl is-active dbus
hostnamectl status

Both commands should return without errors.

Troubleshooting

  • Socket file missing — if /var/run/dbus/system_bus_socket does not exist after starting D-Bus, try rebooting: sudo reboot.
  • D-Bus service not found by systemctl — on minimal or container installs, systemd units may be missing. Reinstall with sudo apt-get install --reinstall dbus.
  • Running inside a container — D-Bus and hostnamectl may not function correctly inside unprivileged LXC/Docker containers. Set the hostname directly via hostname new-name and edit /etc/hostname instead.

Fix D-Bus Permission Errors on Ubuntu/Debian

D-Bus errors related to the launch helper — such as "Could not exec /usr/lib/dbus-1.0/dbus-daemon-launch-helper" — are typically caused by incorrect file ownership or permissions on the helper binary. This guide restores the correct settings.

Prerequisites

  • Ubuntu or Debian system
  • A user with sudo privileges

Steps

1. Fix Ownership of the D-Bus Launch Helper

sudo chown root:messagebus /usr/lib/dbus-1.0/dbus-daemon-launch-helper

2. Fix Permissions (setuid bit required)

sudo chmod 4754 /usr/lib/dbus-1.0/dbus-daemon-launch-helper

The 4754 mode sets the setuid bit (4), gives the owner full access (7), group read and execute (5), and no access to others (4).

3. Restart D-Bus

sudo systemctl restart dbus

Verify

sudo systemctl status dbus
ls -l /usr/lib/dbus-1.0/dbus-daemon-launch-helper

The permissions line should read: -rwsr-xr-- 1 root messagebus

Troubleshooting

  • Permissions reset after upgrade — a package update may overwrite the file. Reapply the chown and chmod commands and report the issue to your distribution's bug tracker.
  • messagebus group does not exist — the group is created by the dbus package. Reinstall it: sudo apt-get install --reinstall dbus.
  • Still failing — check journalctl -u dbus -n 50 for detailed error output.

Install PDFtk on Ubuntu 18.04

PDFtk was removed from the Ubuntu 18.04 official repositories due to a deprecated GCJ runtime dependency. This guide installs it via Snap and fixes the file-not-found error that affects the Snap version by creating a symlink.

Prerequisites

  • Ubuntu 18.04
  • snapd installed (included by default on Ubuntu 18.04)
  • A user with sudo privileges

Steps

1. Install PDFtk via Snap

sudo snap install pdftk

2. Create a Symlink to Fix Path Issues

The Snap-installed binary is confined to its own directory and cannot find files in your working directory without a symlink in the system path:

sudo ln -s /snap/pdftk/current/usr/bin/pdftk /usr/bin/pdftk

If a symlink already exists and needs to be replaced, use the force flag:

sudo ln -fs /snap/pdftk/current/usr/bin/pdftk /usr/bin/pdftk

Verify

pdftk --version
pdftk input.pdf cat output output.pdf

The command should complete without the "Unable to find file" error.

Troubleshooting

  • "Unable to find file" error persists — ensure the symlink points to /snap/pdftk/current/usr/bin/pdftk and not to a stale location. Run ls -la /usr/bin/pdftk to confirm.
  • snapd not available — install it with sudo apt-get install snapd and then retry.
  • Alternative — install from a PPA — if Snap is not suitable, the ppa:malteworld/ppa PPA provides a native PDFtk package for Ubuntu 18.04: sudo add-apt-repository ppa:malteworld/ppa && sudo apt update && sudo apt install pdftk.

Fix /etc/rc.local Commands Not Executing at Boot

Commands placed in /etc/rc.local sometimes fail to run at startup even though the file is executable. This guide covers the most common causes and fixes, including the -e flag trap and the systemd rc-local service.

Prerequisites

  • Ubuntu 16.04/18.04 or Debian
  • Root or sudo access

Steps

1. Remove the -e Flag from the Shebang

The default #!/bin/sh -e shebang causes the script to exit immediately on any non-zero return code. If an early command fails (even silently), later commands never run.

sudo nano /etc/rc.local

Change the first line from:

#!/bin/sh -e

to:

#!/bin/sh

Ensure the file ends with exit 0.

2. Make rc.local Executable

sudo chmod +x /etc/rc.local

3. Enable the rc-local systemd Service (Ubuntu 18.04+)

On Ubuntu 18.04, rc.local is handled by a systemd compatibility unit that may not be enabled by default:

sudo systemctl enable rc-local
sudo systemctl start rc-local
sudo systemctl status rc-local

4. Verify rc.local Exists and is Valid

cat /etc/rc.local

A minimal working example:

#!/bin/sh
/path/to/your/command --args
exit 0

5. Use Full Paths in Commands

At boot, the PATH environment is minimal. Always use absolute paths in rc.local:

# Wrong
mycommand --start

# Correct
/usr/local/bin/mycommand --start

6. Alternative — Use a systemd Service Unit (Preferred)

For reliable startup execution, create a dedicated service unit instead of relying on rc.local:

sudo nano /etc/systemd/system/mycommand.service
[Unit]
Description=My startup command
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/bin/mycommand --args
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
sudo systemctl enable mycommand
sudo systemctl start mycommand

Verify

sudo systemctl status rc-local
journalctl -u rc-local -n 30

Reboot and confirm the desired process is running: ps aux | grep mycommand

Troubleshooting

  • Script exits early — the -e flag in the shebang is the most common cause; remove it.
  • Command not found at boot — use the full binary path, e.g. /usr/bin/php instead of php.
  • Timing issues — if the command needs the network or a mounted filesystem, add the appropriate After= dependency or add a sleep: sleep 10 && /path/to/command.
  • rc-local service not found — install the compatibility package: sudo apt-get install sysvinit-utils.

Fix "Unable to Delete User" Errors on Linux

Deleting a user with deluser or userdel fails when that user still has running processes. This guide shows how to identify and terminate those processes before removing the account.

Prerequisites

  • Ubuntu or Debian system
  • Root or sudo access

Steps

1. Check for Running Processes Owned by the User

ps -aux | grep <username>

If processes appear, they must be stopped before the user can be deleted.

2. Kill All Processes Belonging to the User

sudo pkill -u <username>

For stubborn processes, use SIGKILL:

sudo pkill -9 -u <username>

3. Confirm No Processes Remain

ps -aux | grep <username>

Only the grep process itself should appear in the results.

4. Delete the User

sudo deluser <username>

To also remove the user's home directory and mail spool:

sudo deluser --remove-home <username>

Verify

id <username>

The command should return no such user, confirming the account has been deleted.

Troubleshooting

  • User is logged in via SSH — terminate the SSH session first or use sudo pkill -u username sshd to kill only their SSH processes.
  • Process keeps restarting — disable any systemd services running as that user: sudo systemctl disable --now <service>.
  • userdel vs deluserdeluser is the Debian/Ubuntu-friendly wrapper around userdel. Both require the user to have no running processes.

Install ImageMagick on Ubuntu

This guide installs ImageMagick along with the development libraries needed for PHP, Ruby, Python, and other language bindings on Ubuntu.

Prerequisites

  • Ubuntu 16.04 or 18.04
  • A user with sudo privileges

Steps

1. Update Package Lists

sudo apt-get update

2. Install ImageMagick and Development Libraries

sudo apt-get install -y imagemagick libmagickcore-dev libmagickwand-dev libmagic-dev
  • imagemagick: the core command-line tools (convert, mogrify, identify, etc.)
  • libmagickcore-dev: C development headers for MagickCore
  • libmagickwand-dev: C development headers for MagickWand (used by PHP and other bindings)
  • libmagic-dev: file type detection library headers

Verify

convert --version
identify --version

Both commands should print the ImageMagick version and feature list.

Notes

  • To install the PHP extension for ImageMagick: sudo apt-get install php-imagick followed by sudo systemctl restart apache2.
  • Ubuntu 18.04 ships ImageMagick 6.x. For ImageMagick 7.x, compile from source or use a PPA.
  • ImageMagick default security policy at /etc/ImageMagick-6/policy.xml may restrict certain operations such as PDF conversion. Edit the policy file if needed.

Fix "libtinfo.so.6: cannot open shared object file" on Ubuntu 18

The error "libtinfo.so.6: cannot open shared object file: No such file or directory" occurs when an application compiled against libtinfo.so.6 is run on Ubuntu 18.04, which ships with libtinfo.so.5. Installing the libtinfo6 package from Debian resolves the issue.

Prerequisites

  • Ubuntu 18.04 (bionic)
  • A user with sudo privileges
  • wget or a browser to download the package

Steps

1. Download the libtinfo6 Package

Obtain the package from the Debian archive (choose the version appropriate for your architecture):

wget http://ftp.jp.debian.org/debian/pool/main/n/ncurses/libtinfo6_6.2+20210905-1_amd64.deb

Alternatively, browse http://ftp.debian.org/debian/pool/main/n/ncurses/ to find the latest available version.

2. Inspect the Package (Optional)

dpkg -I libtinfo6_6.2+20210905-1_amd64.deb

3. Install the Package

sudo dpkg -i libtinfo6_6.2+20210905-1_amd64.deb

Verify

ls -la /lib/x86_64-linux-gnu/libtinfo.so.6*

Re-run the application that was failing; the error should no longer appear.

Troubleshooting

  • If the Debian package pulls in unresolvable dependencies on Ubuntu 18.04, try a symlink workaround instead: sudo ln -s /lib/x86_64-linux-gnu/libtinfo.so.5 /lib/x86_64-linux-gnu/libtinfo.so.6. Note this is a workaround and may break if the ABI differs.
  • Replace amd64 in the filename with arm64 or i386 as appropriate for your system architecture.
  • On Ubuntu 20.04 and later, libtinfo6 is available natively: sudo apt-get install libtinfo6.

Install MySQL 5.6 on Ubuntu 16.04

MySQL 5.6 is not available in the default Ubuntu 16.04 repositories, but it can be installed by temporarily adding the Ubuntu 14.04 (Trusty) universe repository which still carries the package.

Prerequisites

  • Ubuntu 16.04
  • A user with sudo privileges
  • No existing MySQL installation (or one that has been fully purged)

Steps

1. Add the Trusty Universe Repository

sudo add-apt-repository 'deb http://archive.ubuntu.com/ubuntu trusty universe'

2. Update Package Lists

sudo apt-get update

3. Install MySQL 5.6

sudo apt-get install -y mysql-server-5.6 mysql-client-5.6

The installer will prompt you to set the root password during installation.

4. Secure the Installation

sudo mysql_secure_installation

Follow the prompts to remove anonymous users, disallow remote root login, and remove the test database.

Verify

mysql --version
sudo systemctl status mysql

Connect and confirm the version:

mysql -u root -p -e "SELECT VERSION();"

Troubleshooting

  • Remove any existing MySQL installation first if there are conflicts: sudo apt-get remove --purge mysql* && sudo apt-get autoremove
  • Warnings about the Trusty repository during apt-get update are expected when mixing releases.
  • Remove the Trusty repository after installation to avoid accidentally upgrading other packages: sudo add-apt-repository --remove 'deb http://archive.ubuntu.com/ubuntu trusty universe'

Install MySQL 5.6 on Ubuntu 18.04

MySQL 5.6 is not available in the Ubuntu 18.04 repositories. This guide installs it from the official MySQL 5.6 generic Linux binary tarball, sets it up as a system service, and configures it to start automatically at boot.

Prerequisites

  • Ubuntu 18.04
  • Root or sudo access
  • Any existing MySQL installation fully removed

Steps

1. Remove Existing MySQL and AppArmor Profile

sudo apt-get autoremove mysql* --purge
sudo apt-get remove apparmor
sudo rm -rf /var/lib/mysql/

2. Create the mysql User and Group

sudo groupadd mysql
sudo useradd -g mysql mysql

3. Download and Extract the MySQL 5.6 Binary

wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
sudo tar -xvf mysql-5.6.46-linux-glibc2.12-x86_64.tar.gz
sudo mv mysql-5.6.46-linux-glibc2.12-x86_64 /usr/local/mysql

4. Set Ownership and Install Dependencies

cd /usr/local/mysql
sudo chown -R mysql:mysql *
sudo apt-get install -y libaio1

5. Initialise the Database

sudo scripts/mysql_install_db --user=mysql

6. Fix Ownership After Initialisation

cd /usr/local
sudo chown -R root mysql
cd mysql
sudo chown -R mysql data

7. Copy Configuration File

sudo cp /usr/local/mysql/support-files/my-default.cnf /etc/my.cnf

8. Start MySQL and Set Root Password

sudo /usr/local/mysql/bin/mysqld_safe --user=mysql &
sudo /usr/local/mysql/bin/mysqladmin -u root password 'YourSecurePassword'

9. Add MySQL to System PATH

sudo ln -s /usr/local/mysql/bin/mysql /usr/local/bin/mysql

10. Register MySQL as a System Service

sudo cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql.server
sudo update-rc.d -f mysql.server defaults

11. Reboot and Verify Autostart

sudo reboot

After reboot:

sudo /etc/init.d/mysql.server status

Verify

mysql -u root -p -e "SELECT VERSION();"

Troubleshooting

  • If mysqld_safe fails to start, check /usr/local/mysql/data/hostname.err for error details.
  • libaio1 is required by the MySQL binary. Install it with sudo apt-get install libaio1 if missing.
  • Verify the init script is registered after reboot: ls /etc/rc2.d/ | grep mysql

Set IPv4 Precedence Over IPv6 on Linux

On some systems, tools like apt-get prefer IPv6 connections and hang when the IPv6 route to a server is unreachable. This guide shows three ways to force IPv4 precedence: editing gai.conf, using a per-command flag, or creating a persistent apt configuration file.

Prerequisites

  • Ubuntu or Debian system
  • A user with sudo privileges

Steps

Option A: Prefer IPv4 System-Wide via gai.conf (Recommended)

Edit the getaddrinfo configuration file:

sudo nano /etc/gai.conf

Find the commented-out line:

#precedence ::ffff:0:0/96  100

Uncomment it by removing the leading hash:

precedence ::ffff:0:0/96  100

Save and exit. This sets IPv4-mapped addresses to a higher precedence, making the system prefer IPv4 connections while still supporting IPv6.

Option B: Force IPv4 for a Single apt-get Command

sudo apt-get -o Acquire::ForceIPv4=true update
sudo apt-get -o Acquire::ForceIPv4=true upgrade

Option C: Force IPv4 for All apt/apt-get Permanently

echo 'Acquire::ForceIPv4 "true";' | sudo tee /etc/apt/apt.conf.d/99force-ipv4

This creates a persistent apt configuration that forces IPv4 for every future apt operation.

Fix Redis Binding Issues (If Applicable)

If Redis or another service is bound to both IPv4 and IPv6 and causing problems, edit its configuration:

sudo nano /etc/redis/redis.conf

Change:

bind 127.0.0.1 ::1

to:

bind 127.0.0.1

Then restart Redis:

sudo systemctl restart redis

Verify

sudo apt-get update

The update should complete without hanging at "Connecting to security.ubuntu.com" or similar.

Troubleshooting

  • If apt-get still hangs, combine Options A and C for the strongest guarantee of IPv4 preference.
  • If you previously disabled IPv6 via sysctl, some services may misbehave because they expect to bind to ::1. Setting IPv4 precedence is preferable to disabling IPv6 entirely.
  • If gai.conf changes have no effect, restart the network or reboot to ensure the NSS configuration cache picks up the change.