Loading icon fonts locally when using Ant Design React framework (instead of alicdn)

Loading icon fonts locally when using Ant Design framework

Don’t use Alibaba’s CDN!

By default, when using Ant Design ReactJS UI framework, icon font are loaded from China’s Ali CDN (run by Alibaba). This may be (and usually is) undesirably behaviour. You may prefer to have a web site that does not call home when you load a page, or leak IP addresses to a third party, this is a security concern.

There are several security issues which have been raised to ant-design, but solutions are not simple to implement.

After some time wasted trying to solve this, this is my quickest and easiest solution.

Normally, you may have the following in your CSS file to import antd’s styles

@import '~antd/dist/antd.css';

We just need to add a few lines below this, to overwrite the font locations, so we get this

@import '~antd/dist/antd.css';
@font-face {
  font-family: 'anticon';
  src: url('./iconfont/iconfont.eot'); /* IE9*/
  src: url('./iconfont/iconfont.woff') format('woff'), /* chrome、firefox、opera、Safari, Android, iOS 4.2+*/
  url('./iconfont/iconfont.ttf') format('truetype'), /* iOS 4.1- */
  url('./iconfont/iconfont.svg#iconfont') format('svg');

You’ll need to download the icon fonts to the ./iconfont/ dir locally. You can get the fonts here:

This should serve fonts locally both in development and also in the built files.

Set up a signage or kiosk machine with Debian 9 Linux

Tested on Debian 9.4.0

Initial installation

Install with debian-9.4.0-amd64-netinst.iso and perform graphical install, partition with MBR and single root partition filling the entire disk without any swap partition. You can use your own partitioning preference if you’d like here.

Choose minimal selections with no graphical desktop environment.

Create the default root user and a separate user tv.

Set up networking if desired, but we’ll assume here you’re using default settings on a network with a DHCP server automatically assigning IP addresses.

Install the following packages as root

apt-get install -y chromium xorg xinit vim openssh-server less curl

Configure ssh (optional)

Create ssh key with ssh-keygen and set up the authorized_keys file. Configure /etc/ssh/sshd_config if desired. On my test machine, I set the following in /etc/ssh/sshd_config

PermitRootLogin yes
PasswordAuthentication yes

You may wish to use PermitRootLogin without-password for better security. Using ssh makes it easier to update remotely. Just ssh into the machine remotely and run your typical apt-get update && apt-get -y dist-upgrade

Enable the service

systemctl enable ssh.service
systemctl start ssh.service

Configure auto login on tty1

Create a new dir:

mkdir -p "/etc/systemd/system/getty@tty1.service.d/"

Then create a new file /etc/systemd/system/getty@tty1.service.d/autologin.conf with:

ExecStart=-/sbin/agetty --autologin tv --noclear %I $TERM

Enable non-graphical console as the default runlevel with

systemctl set-default multi-user.target

Disable console blanking

This probably isn’t needed as we’ll be running X, but it won’t hurt Add the following to the end of /etc/profile

setterm -blank 0 -powersave off &> /dev/null

Disable X blanking

Create a new file /home/tv/.xinitrc and add:

xset s noblank
xset s off -dpms
exec /usr/bin/chromium --kiosk --window-size=1920x1080 'https://YOURWEBSITE.COM/'

I’ve had to use the --window-size option as otherwise it would open with a incorrect window size which only took up half the monitor (not sure of the reason behind this)

Replace the URL with your desired URL to open. I prefer the following, but it allows user to press F11 and exit fullscreen mode, access web developer tools, and the print dialog. This might not be desirable in an actual real kiosk.

exec /usr/bin/chromium --incognito --start-fullscreen 'https://YOURWEBSITE.COM/'

Set up to start X automatically for tv user

Add to the end of /home/tv/.profile

exec startx -- -nocursor

The -nocursor hides the mouse pointer. Don’t use this if you want the mouse pointer to be visible.

Start up

Reboot the machine, on starting up, the machine should autologin with user tv and start X with chromium running, loading your desired URL. You should not be able to exist this shell.

You can open a separate login console at tty2 if you wish by pressing CTRL + ALT + F2.

Shutting down machines

Press the power button. ACPI power shutdown sequence should being.

VirtualBox Notes

Backing up

Just make a copy of the .vbox and .vdi files.

Reducing disk space of dynamic disks.

This doesn’t work for encrypted disks.

On client virtual machine:

  • For Windows
    • Defragment disk, e.g defrag c:
    • Zero free space, e.g sdelete -z c: (sdelete is part of SysInternals)
  • For Linux
    • dd if=/dev/zero of=zeroes bs=1M until there is no space left
    • rm zeroes

Followed by on host computer:

  • VBoxManage.exe modifyhd /path/to/file.vdi --compact

Alternate technique

It may help to defragment and zero free space on existing disk first.

  • Create new VDI of smaller size.
  • Boot GParted or Clonezilla using ISO image, and clone existing disk to the new smaller sized disk (vdi).
  • Change VM settings and boot VM using smaller disk.

Sharing a folder RHEL or CentOS Linux VirtualBox VM

Update VirtualBox Guest Additions modules

Requires gcc and kernel headers installed. If not then run:

yum instal -y gcc kernel-devel-$(uname -r)

Devices > Insert Guest Additions CD image

mount /dev/cdrom /mnt
sh /mnt/VBoxLinuxAdditions.run
umount /mnt

Check module is installed with lsmod | grep vbox. You should see the vboxsfmodule.

Sharing a folder

To attach a folder for sharing:

  • Under Device > Shared Folders – Add your desired folder. Select “permanent” if you want this folder shared all the time.
  • Mount the drive with: mount -t vboxsf FOLDERNAME MOUNTPOINT
  • When finished, umount MOUNTPOINT

To make mount point persistent between reboots, add entry in /etc/rc.local (or /etc/fstab).

Moving Virtual Box VDI

Note This works with encrypted VDI disks.

Virtual machine must be shut down before proceeding.

Backup first!

Backup .vdi and .vbox files. Ths is very important! If you’re using encryption, these keys are inside the vbox file so make sure you back this up to somewhere safe. From now on we don’t touch the backups (unless something goes wrong), we’re referring to the actual working .vdi and .vbox files.


  1. Copy the vdi to the other location, e.g a different hard drive.
  2. In VirtualBox Manager, right click on the machine and remove from the machine list. Select “Remove only” (not “Delete all files”).
  3. Optional: Rename the original vbox file to something else. This is just a sanity check to make sure the machine won’t later find the old VDI.
  4. Open the .vbox file in a text editor. Look for a section that looks a bit like:
    <HardDisk uuid="XXX" location="Windows 8.1.vdi" format="VDI" type="Normal">
    <Property name="CRYPT/KeyId" value="Windows 8.1"/>
    <Property name="CRYPT/KeyStore" value="XXX"/>
  5. Edit the location= part to point to your new vdi location e.g location="E:\New Spot\Windows 8.1.vdi". Note that the location field will not have a drive or path if the vdi file is in the same directory as the vbox file. Save the modified vbox file.
  6. In VirtualBox Manager again, go to Machine > Add, and select your modified vbox file. Check the settings, and they should be the same as before but the drive will be in a different location.
  7. Start and test the machine. If you followed all the steps above exactly, it should be working.
  8. You can safely remove the old vdi file.


  • You can not have disks with the same UUID configured on your system. When you removed the machine from the list, it would have removed the disk from the Virtual Media Manager. If you skipped this remove and add machine part, this process won’t work.


Set up Let’s Encrypt with Nginx web server with webroot plugin

This will allow the Nginx web server to read /.well-known/acme-challenge/ from each domain. This path is used by the webroot plugin.

We’ll need to make a directory to service the challenge files from, we’ll call this /home/www/letsencrypt from now on, and we’ll need to make sure this is set up with appropriate permissions so Nginx can serve these files to the public.

In Nginx’s config, we can add the following to each server block configuration:

location ^~ /.well-known/acme-challenge/ {
    default_type "text/plain";
    root /home/www/letsencrypt;

Generally, adding this in /etc/nginx/global/global.conf and including this file (usually already done by a default install) in each .conf file in each of /etc/nginx/conf.d/ files is recommended.

Install certbot-auto

wget https://dl.eff.org/certbot-auto && chmod a+x certbot-auto && mv certbot-auto /usr/local/bin    

Add a certificate for a domain

certbot-auto certonly --webroot -w /home/www/letsencrypt -d domain.com

Renew all certs if near expiry

certbot-auto renew --webroot -w /home/www/letsencrypt

This can be added as a cron job.

00 2 * * * root /usr/local/bin/certbot-auto renew --webroot -w /home/www/letsencrypt 2> /dev/null

If you wish the automation to apply for a single domain only, use:

00 2 * * * root /usr/local/bin/certbot-auto renew --webroot -w /home/www/letsencrypt --cert-name NAME 2> /dev/null

Certificate names are usually the same as the domain name, however this may not always be the case. You can check your certificate names with:

certbot-auto certificates

To test configuration

certbot-auto renew --webroot -w /home/www/letsencrypt --dry-run

Configure nginx server blocks

In each domain’s server block add:

listen 443 ssl;

ssl_certificate      /etc/letsencrypt/live/domain.com/fullchain.pem;
ssl_certificate_key  /etc/letsencrypt/live/domain.com/privkey.pem;
include ssl/ssl.conf;

In ssl.conf we have:

ssl_session_timeout       5m;
ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache         shared:SSL:10m;
ssl_dhparam               /etc/nginx/ssl/dhparams.pem;

The above SSL config is my personal preference, but you can adjust to your liking.