Category Archives: Server Admin

Server Config, Operations, Tips and Tricks

Example of NGINX reverse proxy config

Common Reverse Proxy

upstream foundation {
    server localhost:18080;
    keepalive 8;

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;


        root /var/www/pwa;
        index index.html;

	location /foundation/ {
		proxy_set_header Connection "";
		proxy_set_header Host $http_host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Frame-Options SAMEORIGIN;
		proxy_pass http://foundation/;

	location / {
                try_files $uri $uri/ /index.html;
#		try_files $uri $uri/ =404;
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mattermost_cache:10m max_size=3g inactive=120m u$

server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;

        index index.html;

   location ~ /api/v[0-9]+/(users/)?websocket$ {
       proxy_set_header Upgrade $http_upgrade;
       proxy_set_header Connection "upgrade";
       client_max_body_size 50M;
       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Frame-Options SAMEORIGIN;
       proxy_buffers 256 16k;
       proxy_buffer_size 16k;
       client_body_timeout 60;
       send_timeout 300;
       lingering_timeout 5;
       proxy_connect_timeout 90;
       proxy_send_timeout 300;
       proxy_read_timeout 90s;
       proxy_pass http://localhost:8065;

   location / {
       client_max_body_size 50M;
       proxy_set_header Connection "";
       proxy_set_header Host $http_host;
       proxy_set_header X-Real-IP $remote_addr;
       proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
       proxy_set_header X-Forwarded-Proto $scheme;
       proxy_set_header X-Frame-Options SAMEORIGIN;
       proxy_buffers 256 16k;
       proxy_buffer_size 16k;
       proxy_read_timeout 600s;
       proxy_cache mattermost_cache;
       proxy_cache_revalidate on;
       proxy_cache_min_uses 2;
       proxy_cache_use_stale timeout;
       proxy_cache_lock on;
       proxy_http_version 1.1;
       proxy_pass http://localhost:8065;

Ansible First Impression

I have tested out Ansible recently for Server admin, the experience is nice but it may take time to understand the whole eco-system.

There are a few concepts to understand before hand

Ansible uses SSH to execute Python Code in the Client machine, therefore, the Client needs to install OpenSSH and Python by default. It looks up Python 2 by default, a custom parameter is needed to instruct Ansible to use Python 3 instead. Everything makes sense if follows this direction.

Ansible Playbook is the script that drives the client machines to work, there are a lot of build in modules in Ansible. Worst case scenario is using the shell script module to write all commands. In this case, the script may only execute once, and may have side effect if execute more than once.

Ansible Collections and Roles are pre-built extensions for Ansible, a role usually serve one function, for example, managing sysctl.conf service or managing Grub. A collection is a collection of Role that may have multiple functions.

Ansible Galaxy is the marketplace of Ansible Collections and Ansible Roles. However, only those frequently downloaded scripts are useful in general. Others are just for a niche use cases.

Finally, the Ansible comes with Ubuntu 18.04 APT repo are outdated(Version 2.5), you need version 2.8 or 2.9 to be useful. You can install by installing the via installing the Ansible APT library.

sudo apt update
sudo apt install software-properties-common
sudo apt-add-repository --yes --update ppa:ansible/ansible
sudo apt install ansible

Installing OracleXE 18 on CentOS on Proxmox VE LXC

Installing Oracle used to be a tedious and error prone operation, it takes my inexperienced colleague a week, but still cannot fix it. I have fixed the server and would make note on the procedures to install Oracle so that I won’t spend too much time on it next time.

Basically I follow the RHEL steps in the following links. CentOS on LXC is exactly the same in the following link.

I need to prepare the environment first as followed. Everything is done by “root”

  • Host Table – Hard Code the hostname in /etc/hosts, with the following line    OracleCentOS
  • Disable IPv6 – seems IPv6 doesn’t work very well in Oracle XE 18, I can only connect locally (with port forwarding) but not from another machine. 
    edit /etc/sysctl.conf , amend the following two lines at the end of filenet.ipv6.conf.all.disable_ipv6 = 1
    net.ipv6.conf.default.disable_ipv6 = 1
  • Install curl for subsequent installation steps
    yum install curl
  • Restart server to make every thing effective. 
    shutdown -r now

And then we could follow the above link “Red Hat compatible Linux distribution” section to install the Oracle

We can get an up-and-running Oracle up to now, however, it can only be connect by sqlplus, you cannot connect to it from external. It is due to the listener settings is not correct yet. So, we need to go through a few post installation configuration steps.

  • Setup the Oracle default DB
    /etc/init.d/oracle-xe-18c configure
  • Modify tnsname.ora and listener.ora, use hostname OracleCentOS and port 1521
    vi /opt/oracle/product/18c/dbhomeXE/network/admin/tnsnames.ora

tnsnames.ora Network Configuration File: /opt/oracle/product/18c/dbhomeXE/network/admin/tnsnames.ora
Generated by Oracle configuration tools.
XE =
(ADDRESS = (PROTOCOL = TCP)(HOST = OracleCentOS)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = OracleCentOS)(PORT = 1521))

  • vi /opt/oracle/product/18c/dbhomeXE/network/admin/listener.ora

      (ADDRESS = (PROTOCOL = TCP)(HOST = OracleCentOS)(PORT = 1521))

  • Restart the oracle service by the following command 
    /etc/init.d/oracle-xe-18c restart
  • You can verify port 1521 opens with the following command
    netstat -anp | grep 1521

You should be able to connect to the Oracle via IP as sysdba in SQLDeveloper

it is strange that I cannot simply use SQLDeveloper to create user, we need to modify the final SQL to create user a bit.

Therefore, what we do is to add this line in the SQL tab during create user.
alter session set "_ORACLE_SCRIPT"=true;  

PostgreSQL + TimescaleDB + MadLib installation

PostgreSQL is a very very powerful database engine by itself, there are many advanced functions which is far beyond the standard SQL query.

The following combo are great as a starting point with the following functionality.

TimescaleDB – Time Series Database, support time based partitioning of data sharding.

MadLib – a DB extension to carry out common Machine learning program within the DB.

Here are the installation steps.

# install PostgreSQL and PGXN client
deb bionic-pgdg main
wget --quiet -O - | sudo apt-key add -
sudo apt-get update
sudo apt-get -y install postgresql-10 libpq-dev postgresql-server-dev-10 postgresql-plpython-10 pgxnclient cmake g++ m4

# Include the TimescaleDB PPA
sudo add-apt-repository ppa:timescale/timescaledb-ppa

sudo apt-get update

# Install the TimescaleDB
sudo apt install timescaledb-postgresql-10
sudo timescaledb-tune --quiet --yes

# Install MADLib
sudo pgxnclient install madlib
sudo pgxnclient load madlib 

# Install CStore
sudo apt-get install bison flex git libreadline-dev libz-dev git libpq-dev libprotobuf-c0-dev make protobuf-c-compiler
sudo pgxn install cstore_fdw
sudo pgxn load cstore_fdw

After you installed all of them, you may play around with the example.

For each newly created db, we need to enable the extensions, for example.

CStore Reference

CREATE DATABASE testdb OWNER=jimmy LC_COLLATE='C' LC_CTYPE='C' template=template0;
GRANT ALL ON DATABASE testdb to jimmy;
\c testdb
CREATE SERVER cstore_server FOREIGN DATA WRAPPER cstore_fdw;

Setup IBM MQ on Ubuntu

My recently is recently integrating with a banking solution via IBM MQ, I need to install an IBM MQ for testing. Here are my steps for the installation

PS. IBM MQ 9.1 requires IPv6 for all communication, so, I fall back to IBM MQ 8.0

1. Download IBM MQ binary from IBM Website

2. Follow the following link for the installation

3. After installation, add ubuntu user (current user) to the “mqm” group

sudo usermod -aG mqm $USER

4. Up to now, the installation should be completed.

5. Setup Env and Queue Manager

There is a default MQ Installation (Installation1) setup, you can use the installation directly.

The program directory is /opt/mqm , you can find all command in /opt/mqm/bin , all subsequent execution are in that folder.

6. Create the MQ Manager

crtmqm QM1
strmqm QM1

7. Download the sample script from the following link, it will create some default queue and settings.

Modify the script, change the user from “app” to “ubuntu”


Execute the script

./runmqsc QM1 < ~/mq-dev-config.mqsc

8. MQ Server uses Linux user and user group for authentication and authorization, so, we need to assign more MQ Server privilege to Linux user group (mqm)

./setmqaut -m QM1 -t qmgr -g mqm +connect +inq
./setmqaut -m QM1 -n DEV.** -t queue -g mqm +put +get +browse +inq

9. Finally, since IBM MQ 7.5, Channel would also require authentication, but I have no idea on how it works yet, so the simplest solution is disabled that.

./runmqsc QM1

PS. We should figure out how to work properly with the channel authentication.

10. Testing with MQ Explorer

Install IBM MQ Explorer from the following link

You can use MQ Explorer to connect to .39 MQ Queue Manager.

ActiveMQ Artemis quick start notes

I have played around with Artemis for a few days, here are the useful command I used. The exact config is stored at my github.

1. Create 2 brokers with port offset
artemis create mybroker1 –port-offset 0
artemis create mybroker2 –port-offset 0

2. Testing the producer and consumer
./artemis producer –url tcp://localhost:61616
./artemis consumer –url tcp://localhost:61616

3. Enabled clustered
See jgroup.xml and broker.xml , and

4. Load balancing
See broker.xml, Add in

5. Enable SSL for HornetQ OpenWire protocol
a. Provide keystore.jks and truststore.jks
b. Config the acceptor in broker.xml

MiniDLNA configuration

MiniDLNA is a uPnP server that allow you to play Video, Picture and Music over LAN via IP broadcasting protocol.

I have installed it in my Raspberry Pi as a mini-server at home, to stream video to my TV and my XiaoMi TVBox.

By default, it runs with “minidlna” user, it may not be so convenient for use because it is not a usual user, I need to manually copy files to the Pi and subsequently to the folder accessible by minidlna. It is related to the user privilege issue. Funny enough, simply change on folder to 666 doesn’t solve the problem because minidlna requires to access the folder along the path from “/”

Therefore, the only solution is to configure MiniDLNA to run on another user account rather than the default minidlna user.

The minidlna.conf is as followed

# Specify the user name or uid to run as.

Install Superset with Ubuntu 16.04 with venv

sudo apt-get install build-essential libssl-dev libffi-dev python-dev python-pip libsasl2-dev libldap2-dev python3-dev

python3 -m venv superset-venv

source superset-venv/bin/activate

pip install --upgrade setuptools pip

pip install superset

# The following copy from

# Create an admin user (you will be prompted to set username, first and last name before setting a password)
fabmanager create-admin --app superset

# Initialize the database
superset db upgrade

# Load some data to play with
superset load_examples

# Create default roles and permissions
superset init

# Start the web server on port 8088, use -p to bind to another port
superset runserver

Ubuntu KVM virtualization with GPU Passthrough

Linux is equipped with KVM, which is another hypervisor at the same level of VMWare and VirtualBox. However, it has the great capability for GPU pass through, which grant the guest system to access GPU natively.

The function is great, but the setup is a bit complicated because it involves low level configuration of Linux to mask the GPU away from kernel, which allow the guest to use it exclusively.

To do so, we need to do the following steps.
1. Install the KVM as followed

sudo apt-get install qemu-kvm libvirt-bin virtinst bridge-utils cpu-checker virt-manager ovmf

2. Rebuild the initramfs for the kernel, so that it can load before proper Radeon or AMDGPU load.

[email protected]:~$ cat /etc/modules
# /etc/modules: kernel modules to load at boot time.
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.
[email protected]:~$ 

[email protected]:~$ cat /etc/initramfs-tools/modules 
# List of modules that you want to include in your initramfs.
# They will be loaded at boot time in the order below.
# Syntax:  module_name [args ...]
# You must run update-initramfs(8) to effect this change.
# Examples:
# raid1
# sd_mod
pci_stub ids=1002:683d,1002:aab0
[email protected]:~$ 
[email protected]:~$ sudo update-initramfs -u

3. Config the kernel to load vfio-pci before loading any GPU driver, also blacklist the GPU hardware ID which look up in “lspci -nnk”. Furthermore, you can verify the status with “lspci -nnk” make sure the driver for GPU is vfio-pci rather than radeon

[email protected]:~$ vi /etc/modprobe.d/vfio.conf 
softdep radeon pre: vfio-pci
softdep amdgpu pre: vfio-pci
options vfio-pci ids=1002:683d,1002:aab0 disable_vga=1
01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde XT [Radeon HD 7770/8760 / R7 250X] [1002:683d]
	Subsystem: PC Partner Limited / Sapphire Technology Cape Verde XT [Radeon HD 7770/8760 / R7 250X] [174b:e244]
	Kernel driver in use: vfio-pci
	Kernel modules: radeon, amdgpu
01:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] [1002:aab0]
	Subsystem: PC Partner Limited / Sapphire Technology Cape Verde/Pitcairn HDMI Audio [Radeon HD 7700/7800 Series] [174b:aab0]
	Kernel driver in use: vfio-pci
	Kernel modules: snd_hda_intel

4. It is not a good practice to run libvirtd with root, but it is a quick way to let libvirtd to access an attachable storage.

Changing /etc/libvirt/qemu.conf to make things work.
Uncomment user/group to work as root.
Then restart libvirtd

The following are the reference I checked

Linux Software Raid 1

First, install the Multi Disk Admin tools

sudo apt-get install initramfs-tools mdadm 

Next, set the Partition Type to “fd Linux raid auto”

sudo fdisk /dev/sdb
sudo fdisk /dev/sdc

Create the MD(md0)

sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb1 /dev/sdc1

Format the partition with Ext4

sudo mkfs.ext4 /dev/md0

Command to check RAID status

sudo mdadm --query /dev/md0
sudo mdadm --detail /dev/md0