5 tips on future proofing your Medium posts

So, you’ve decided you want to blog or write on Medium – where all the cool kids hang out. Great. Remember there are other similar platforms to write and blog and at some point Medium (like everything else on the Internet) might lose its appeal or even, god forbid, shutdown.Dont break da internetz

When that happens, what will happen to your posts? How can you and the rest of the internet reach it?

There were numerous occasions in the past (the most recent one was Posterous) where the platform simply died and all the links pointing to it and all of their SEO goodness went to shaite.

You can always run your own server, but not everyone has the time, power or know-how to do so.

Here are few tips to help you be forward compatible with most platforms in the future:

  1. Choose a platform that supports a custom domain. If you can’t blog under your own domain you will never truly own your content.
  2. Make sure to blog under your own domain (or subdomain such as blog.mycooldomain.com). If you don’t own a domain – get one. It’s very cheap as it costs anywhere between ~$3-$10/year depending on the type .com, .net, .co and domain registrar (I like namecheap.com). Medium added support for that on March 2015 so you have no excuse.
  3. Make sure you have some sort of backup for your posts. I usually like to write my posts without formatting on Google Docs or Simplenote so I get an immediate backup. Before publishing I copy the content to the publishing platform I use. Doing so will make sure that even if your platform goes down you can always restore your posts using your domain and back up of the posts. Another benefit is that you don’t need to rely on an export feature that your dying platform may or may not provide.If you are slightly more technically advanced I suggest writing the posts in Markdown. There are various tools to generate better looking HTML that you can later paste into your current cool blogging site.
  4. Make backups of attached/uploaded resources. If your posts contain images or other resources that you have uploaded to your chosen platform, make sure to have copies of these files so that you can always restore it with the post text in other platforms if needed.
  5. Save all of your posts’ URLs. Make a document or spreadsheet of all your posts’ URLs. For example, if a blog post URL is http://mycooldomain.com/2015/12/31/something-cool make sure to copy and save it. If your chosen blogging platform goes down you can always add a redirect rule from the old URL (as it appeared in the old platform) to how it will appear in the new one, thus not breaking da internetz!

These rule don’t apply just to Medium, they apply to most platforms such as WordPress (wordpress.com or self hosted one), any static site generator, Ghost, Svbtle, Squarespace, Weebly, etc.

In my opinion, the best choice nowadays for people who don’t want to mess around with server is to use a static site generator such as Jekyll. While it involves running a few commands in your shell (that black screen with running white text) you can easily build a site, generate it and host it on platforms such as Surge or Netlify.

Lets Encrypt Error: The server could not connect to the client to verify the domain :: Failed to connect to host for DVSNI challenge

Are you using Lets Encrypt? (If not, you should go ahead and use it to generate SSL certificates to ALL of your web servers).

If you want to run it on EC2 or GCE using the –standalone argument (./letsencrypt-auto certonly –standalone -d example.com) make sure port 443 (for SSL) is open on that server.

Otherwise you’ll get the infamous:

The server could not connect to the client to verify the domain :: Failed to connect to host for DVSNI challenge

Go ahead. Install it. Today.

UIImage in iOS 5, Orientation and Resize

One of the things I found very strange is the fact that most operations that came with iOS prior iOS 5 which revolved around UIImage didn’t take into account the orientation of the image. This meant that if you want to read a picture from the camera roll and resize it, you’d have to roll your own code to correctly flip and/or rotate the image according to its orientation value.

Being my lazy self I used the fine code of Trevor Harmon in UIImage+Resize. Trevor added some categories to make handling UIImage a bit nicer. The code takes create of everything including orientation.

My app worked great on iOS 4 and early betas of iOS 5, however in the late beta of iOS 5 and in the release it wrongfully rotated the images.

After further investigation it seems iOS 5 already rotates the image correctly. UIImage+Resize rotated it again, causing the images to get skewed.
A quick fix would simply avoid the transposition code in UIImage+Resize.

Since the code ran perfectly fine in iOS 4, for backwards compatibility I added a check for OS version and for anything below 5.0 the old code would work.
Check out this gist:

For better performance I would store a boolean flag somewhere in the app saying you are running in iOS 5 and check that instead of keep on checking the OS version every run, but this is just to get you started.

Clone S3 Bucket Script

I had to backup an S3 bucket so I whiped out a small script to clone a bucket.

It’s written in Python and depends on the excellent Boto library. If you are running Python < 2.7 you’ll also need the argparse library (both available also via pip).

View the gist here: https://gist.github.com/1275085

Or here below:

PPTP VPN on Ubuntu 10.04 for your iPhone / iPad

Below are the steps necessary to connect your iPhone / iPad or any other computer via a PPTP VPN.

Why would I want to do this? For various reasons such as allow you to access information and servers that are behind a firewall, or maybe you just need to route traffic through different servers.

I’ve tested this on a 256mb Rackspace Cloud instance running Ubuntu 10.04 and with an iPhone and an iPad. Thanks to Yaniv for debugging the instructions.

Disclaimer: This is for educational uses only and I take no responsibility as to what you may do with it. The PPTP VPN setup via the instructions below has no encryption and uses the simplest and lowest form of password authentication. If you require stricter encryption and authentication methods you’ll need to read more about pptpd configuration.


  • The instance you are using is blank, specifically from firewall rules in iptables, otherwise, you’ll need to patch things up.
  • All commands assume you are current a root user. If you logged in as root, that’s great. If not, run:
    sudo su
  • Instead of messing a lot with iptables commands, I’m using ufw (Uncomplicated FireWall). In general, to most people, it will be easier to manage and work with.

Setting up the PPTP Server

In general we are going to create a PPTP VPN that is very basic without encryption and with basic authentication security (not fancy authentication protocols). Since Rackspace Cloud instance has an external interface (eth0) that has the instance public IP and an internal interface (eth1) with an internal IP used to communicate with your other Rackspace Cloud server (if you have them), we’ll create an alias network interface card that will have some other set of internal ips, which will be given to the devices connected via the VPN.

  1. Install the necessary software (pptpd, pptp-linux, ppp and ufw – for firewall):
    apt-get install pptpd pptp-linux ppp ufw
  2. Enable port 22 (ssh) in the firewall, so we don’t get locked out of our instance:
    ufw allow 22
  3. Enable port 1723 (pptpd) in the firewall to enable access to the pptpd dameon:
    ufw allow 1723
  4. Enable ufw:
    ufw enable
  5. Add an aliased network interface card (eth0:0): (We use the address space of since its usually free for most networks for most users. You can feel free to change this address if it is already taken)
    Edit /etc/network/interfaces:

    nano /etc/network/interfaces

    Enter the following text at the end of the file:

    auto eth0:0
    iface eth0:0 inet static
    gateway (same value as listed for eth0)
    dns-nameservers (same value as listed for eth0)

    Replace the value of “gateway” with the same value you will see in this file for “eth0”, the real public network interface.
    Replace the value of “dns-nameservers” with the same value you will see in this file for “eth0”

  6. Configure the pptpd daemon:
    Edit /etc/ppp/pptpd-options:

    nano /etc/ppp/pptpd-options

    Comment out (add a “#” char at the start of the line) the following lines:
    “require-mppe-128″replace “#ms-dns” with “ms-dns”
    replace “#ms-dns” with “ms-dns”

    The last 2 lines above sets the DNS server the devices connecting to your PPTP VPN will use. The addresses above are for the Google Public DNS server, but can be any other DNS server (including the same DNS servers as Rackspace or your hosting provider use)

    Edit /etc/pptpd.conf :

    nano /etc/pptpd.conf

    Add at the bottom of the file:


    The value of “remoteip” will be the set of IP addresses the devices connecting to the VPN will get upon successful connection. Currently, we have here 18 addresses, which is enough for 18 concurrent devices. You can make this range bigger if needed.

  7. Configure the username and password that will be used to authenticate client accessing the VPN:
    Edit /etc/ppp/chap-secrets:

    nano /etc/ppp/chap-secrets
    # client server secret IP addresses
    [UserName] pptpd [Password] *

    Replace [UserName] with the username you wish to use.
    Replace [Password] with the password you wish to use (I suggest a long random password. Try this generator)

  8. Enable IP forwarding in the kernel:
    Edit /etc/sysctl.conf :

    nano /etc/sysctl.conf

    Uncomment the line “net.ipv4.ip_forward=1”
    For IPv6, uncomment “net.ipv6.conf.all.forwarding=1”

  9. Enable IP forwarding in ufw:
    Edit /etc/default/ufw:

    nano /etc/default/ufw

    Change the value of “DEFAULT_FORWARD_POLICY” from “DROP” to “ACCEPT”

  10. Add IP masquerading rule in ufw, so that NAT will work and devices connecting to the VPN will be seen as if the traffic goes out of the VPN server:
    Edit /etc/ufw/before.rules:

    nano /etc/ufw/before.rules

    Paste the text below after the header and before the “*filter” rules:

    # nat Table rules

    # Allow forward traffic from eth0:0 to eth0

    # don’t delete the ‘COMMIT’ line or these nat table rules won’t be processed

  11. Reboot the machine, cross your fingers and hope for the best :-)

Configuring your iPhone / iPad

  1. In your iPhone / iPad go to “Settings” -> “General” -> “Network” -> “VPN”
    PPTP VPN Configuration
  2. Select “Add VPN Configuration”
  3. Select “PPTP”
  4. In “Description” enter the name of the VPN connection
  5. In “Server” enter the IP address of the server (or a server name, if you mapped the server’s IP address to a domain name)
  6. In “Account” enter the username you have entered into the “/etc/ppp/chap-secrets” file
  7. In “Password” enter the password you entered for the above username in “/etc/ppp/chap-secrets”
  8. Make sure “Send All Traffic” is turned to “ON”
  9. Set “Encryption Level” to “None” (this is how we configured the PPTP server in this post, if you setup an encryption try to keep it in “Auto”
  10. Select save


Varnish High, Ever increasing CPU usage workaround

If you are using Varnish version >= 2.1 and experiencing an ever increasing CPU usage up to a point where you need to restart the service to force CPU usage to drop you may want to add the “-h classic” argument to the command line.

This will revert to use the older hashing method instead of the newer “critbit” that was first introduced in version 2.1.

You can read a little bit more about it on the Yedda Dev Blog.

Disco Tip – Crunching web server logs

At my day job we use Disco, a Python + Erlang based Map-Reduce framework, to crunch our web servers and application logs to generate useful data.

Each web server log file per day is a couple of GB of data which can amount to a lot of log data that needs to be processed on a daily.

Since the files are big it was easier for us to perform all the necessary filtering of find the rows of interest in the “map” function. The problem is, that it requires us to return some generic null value for rows that are not interesting for us. This causes the intermediate files to contains a lot of unnecessary data that has the mapping of our uninteresting rows.

To significantly reduce this number, we have started to use the “combiner” function so that our intermediate results contains an already summed up result of the file the node is currently processing that is composed only from the rows we found interesting using the filtering in the “map” phase.

For example, if we have 1,000 rows and only 200 answer a certain filtering criteria for a particular report, instead of getting 1,000 rows in the intermediate file out of which 800 have the same null value, we now get only 200 rows.

In some cases we saw an increase of up to 50% in run time (the increase in speed is the result of reducing less rows from the intermediate files), not to mention a reduction in disk space use during execution due to the smaller intermediate files.

That way, we can keep the filtering logic in the “map” function while making sure we don’t end up reducing unnecessary data.

Ubuntu 9.10 Karmic Koala and ies4linux – Installation

Installing ies4linux on Ubuntu 9.10 Karmic Koala by just running “./ies4linux” might show some warnings such as:

IEs4Linux 2 is developed to be used with recent Wine versions (0.9.x). It seems that you are using an old version. It’s recommended that you update your wine to the latest version (Go to: winehq.com).

In my case it showed the above text, which seems to be a warning, and run the UI but then got stuck and didn’t complete anything.

To overcome this issue simply run the installation without the GTK based UI in a terminal window:

./ies4linux –no-gui

That’s it. Works like a charm.

Google AppEngine – Python – issubclass() arg 1 must be a class

If you are getting the error “”issubclass() arg 1 must be a class”” with Google App Engine SDK for Python on Linux its probably because you are running Python 2.6 (and will probably happen to you when you run Ubuntu 9.04 – 2.6 is the default there).

Just run the dev server under python 2.5 (i.e. python2.5 dev_appserver.py)

Error: “Operation could not be completed (error 0x000006d1)” when adding a Samba based network printer to Vista

If you are getting the following error while adding a Samba based network printer to Vista:

Windows cannot connect to the printer. Operation could not be completed (error 0x000006d1).

And you have a Samba server (version 3.0 and above) consider using the following technique to add the printer:

  • Add a local printer (not a network one!)
  • Select “create a new port”
  • Select “Local port” as type of port
  • In the port name enter the printer’s SMB path, i.e. \\sambaserver\printer_name
  • Select the right driver

That’s all. Works like a charm!

If you have an older version of Samba (< 3.0) know that Vista uses NTLMv2 by default. Follow these instructions to revert back to NTLMv1 by default (also true for regular shares).

Also note that since this is a local printer that prints to a print queue on the Samba server, you might not be able to delete print jobs that were completely sent to the Samba server print queue, since we essentially created a local queue.