Tuesday, May 9, 2017

Mautic Nginx Configuration and Setup


Just a quick example of how to setup Mautic using Nginx.

server {
listen 443;
    server_name mautic.example.com;

ssl on;
    ssl_certificate /etc/letsencrypt/live/mautic.example.com/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/mautic.example.com/privkey.pem; # managed by Certbot

    access_log /var/log/nginx/mautic_access.log;
    error_log /var/log/nginx/mautic_error.log;

    client_max_body_size 50m;

    gzip on;
    gzip_proxied any;
    gzip_types       text/css text/plain text/xml application/xml application/javascript application/x-javascript text/javascript application/json text/x-json;
    gzip_vary        on;
    gzip_disable     "MSIE [1-6]\.";

    root /home/example/mautic;
    index index.php index.html index.htm;

    # redirect index.php to root
    #rewrite ^/index.php/(.*) /$1  permanent;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
    }
}

Tuesday, January 24, 2017

Interview Question: How would you architect Uber?

There was recently a thread on hacker news about what questions you would ask a software architect. One of the questions was how you would architect Uber:

I would probably divide up the architecture into the following pieces:

  • Driver App
  • Passenger App
  • Backend Server


Let’s architect out the driver experience first. Drivers need to be onboarded so figure a whole system just for onboarding a driver. Once drivers are in the system we need to be able to track their location whenever they are ready to accept rides. So the app at a bare minimum needs to be able to constantly relay the driver’s current location to the backend server.

This needs to be updated in real time. I may look toward a messaging bus/queue for these types of updates so I can throw location updates out if get too behind. I would look at how multiplayer games like Quake implemented reporting real time location to the server as fast as possible and with as little delay as possible.

Once the backend server has the location we can look to the passenger app to do almost the same thing. The passenger app at a minimum needs to report trips that people want to take. Basically source and destination location.

Once we have both in the system we can now creating a matching algorithm or module. I would base this on how stock markets match and route orders. There are a number of different techniques for this. I would model the drivers as ask orders and the passenger requests as buy orders. Once a driver has been matched to a passenger we can send them both notifications and provide updates along the way.

Keep in mind that this is really only for traditional Ubers with one passenger. With pools the matching algorithm becomes more complex as well as the infrastructure to support it.

Monday, January 23, 2017

Developing for the NRF51822 on Mac OS X

Over the weekend I worked on trying to get a development environment up and running for the Nordic nRF51822 system on a chip.

This outlines how I did it:

Need to Download Segger JLink. This is used to flash the board.

J-Link Software and Documentation pack for MacOSX
https://www.segger.com/downloads/jlink?step=1&file=JLinkLinuxDEB64_4.94.3

For Mac I installed: JLink_MacOSX_V612f.pkg


After it was installed I was able to run JLinkExe (it put it in my path)

$ JLinkExe 
SEGGER J-Link Commander V6.12f (Compiled Jan 13 2017 16:41:09)
DLL version V6.12f, compiled Jan 13 2017 16:40:56

Connecting to J-Link via USB...Updating firmware:  J-Link OB-SAM3U128-V2-NordicSemi compiled Nov 14 2016 16:58:29
Replacing firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled May  4 2015 13:48:48
Waiting for new firmware to boot
New firmware booted successfully
O.K.
Firmware: J-Link OB-SAM3U128-V2-NordicSemi compiled Nov 14 2016 16:58:29
Hardware version: V1.00
S/N: 681696138
VTref = 3.300V


Type "connect" to establish a target connection, '?' for help

J-Link>


I had to use SWD:


JLinkExe -device nrf51822 -if swd -speed 2000



J-Link>loadfile nrf51422_xxac.hex
Downloading file [nrf51422_xxac.hex]...
Comparing flash   [100%] Done.
Erasing flash     [100%] Done.
Programming flash [100%] Done.
Verifying flash   [100%] Done.
J-Link: Flash download: Flash programming performed for 1 range (4096 bytes)
J-Link: Flash download: Total time needed: 0.132s (Prepare: 0.043s, Compare: 0.004s, Erase: 0.000s, Program: 0.075s, Verify: 0.001s, Restore: 0.008s)
O.K.

J-Link>

Tuesday, September 27, 2016

Google for Work Referral Codes


I occasionally get some promotion codes for Google Apps. These promotion codes give you $10 off per user for a year.

Here are the instructions for redeeming:

1. Use my referral link (http://goo.gl/2SJHuh)
3. Promotion codes expire in six months.
4. Promotion codes will only work in the US. If you need some for Canada let me know.

Promotion codes: 

  • KANEA9NQUM47XLA
  • KCV4Y7NGHRUECTM
  • L3QY9WXKMCVUGQL
  • L4XHXUQLGKALJ3A
  • L7FJJDC7JAMNW9X
  • L9UKK3YQ7HMLFKA
  • LC7GVN6AAR4QANC
  • M33TR9MJJA9P66J
  • M4CAWERL67WWTEX
  • M6LMATUHUEC9VR4
  • M7U4Y4JCFY3HJDT
  • MA6QDM9M37D7Q4T
  • MCLWVCAF99XP3FJ
  • N3F7KTFDRQWAKCR
  • N4PDUWWCQTV4FCH
  • N6YWFU43N9JYMNY
  • N9EPVWLQ9GNGXXQ
  • NAQNTMQFUYFLXMY
  • NCWQ37Y774JFV74
  • P3YJQF3FAVFRRY6
  • P6FWA7MPU6ML97L
  • P7RPFRY9P6RRWWM
  • PA7FUTD7D7PL9DW
  • PCJ6RNFG6MR3MCJ
  • Q3FW6PXGGXTC476
Have fun!

Saturday, November 28, 2015

Troubleshooting rtorrent: Storage error: [File chunk write error: Invalid argument.]


So I decided to try and improve the performance of one of my VMs that was running torrents.

Instead of using samba to mount the filesystem from inside the guest I went with QEMU / KVM's v9fs.

The filesystem is actually called 9p or Plan 9 File System:

https://www.kernel.org/doc/Documentation/filesystems/9p.txt

After mounting and figuring out permission issues I started rtorrent and got the error

[File chunk write error: Invalid argument.]

Apparently rtorrent uses mmap and the Plan9 file system kernel module did not support memory mapping. However it was added in a later kernel release. So all I had to do was upgrade my kernel (I was on the default 14.04 LTS kernel):


sudo apt-get install linux-image-generic-lts-vivid linux-headers-generic-lts-vivid

Restarted and used the following mount command it all worked:

mount -t 9p -o trans=virtio,version=9p2000.L,cache=mmap,rw /mount/external /data

Before the cache=mmap did not work (only cache=loose or cache=none)

Monday, April 13, 2015

Making your Windows KVM guest boxes fly with VirtIO



In order to extract the maximum performance out of a Windows guest OS on KVM / qemu you should install VirtIO.

What is virtio?

There are quite a few articles about it but basically it is like the VMWare Tools for KVM. It is a bunch of libraries that basically speed up your guest OS by making it more efficient to communicate with the host.

What speed ups are we talking about? Mainly disk I/O and network. Without Virtio drivers installed your Windows guest will feel like molasses. Or more like the difference between traditional hard drives and SSDs. It will still work but you won't like it.

What tripped me up about install the drivers was that everywhere I looked it said to download them from the Fedora project here: http://alt.fedoraproject.org/pub/alt/virtio-win/stable/.

The problem is I was using Ubuntu so while you can install the drivers it just blue screens on you with a giant STOP error. Basically I was using the wrong drivers.

I am on Ubuntu 14.04 LTS so what I really wanted was this: https://launchpad.net/kvm-guest-drivers-windows/+download


The overall technique is setup a device that uses virtio in the libvirt configuration file for your guest. This is an xml configuration file you access by typing virsh and then "edit <name>".

After you do this you will want to specify a specific network card or disk that has type="virtio". This will cause Windows to detect a new type of device in Device Manager. You then update the driver by using the downloads found on launchpad.

If you are lucky you will see the following:


Both should say "packaged by Canonical". These are the major drivers you will want. The other is a serial driver and then a balloon driver. The balloon driver is for dynamic memory management.

If you are wondering why you don't need to install these drivers on Linux guests it is because linux guests have it compiled into the kernel by default.



Saturday, April 11, 2015

Generating your own GPG key on Windows



Generating your own GPG key on Windows


End to end encryption is important. One of the critical pieces is having your own public/private key pair. Here is how you generate one on Windows.

Download gpg4win here:

http://gpg4win.org/download.html

The latest release was Gpg4win 2.2.4. Go ahead and install it making sure you also install Kleopatra (a tool for managing keys and certificates).

Start Kleopatra and go to "File ---> New Certificate", Select "Create an OpenPGP key pair". Everything you put here will be publicly visible. Click on Advanced settings and make sure RSA 4096 bit is selected (stronger crypto) and select Authentication for Certificate Usage (as well as the others). Select a passphase to protect your private key (it is not needed but strongly suggested).

You should get along with a Fingerprint (yours will vary)

Certificate created successfully.
Fingerprint: 6E18EAD1C783F2B2964A949E9F4567CF161EA82D

At this point you should Make a backup of your keypair and upload the certificate to a public server. I personally use the MIT keyserver. After this you should public your PGP keyblock somewhere no one else can access and call it your own so other people can send you encrypted things. Example here is mine:



-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v2

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
RDHCLFVsnJ2guAkXEHY=
=FzKZ

-----END PGP PUBLIC KEY BLOCK-----